Studi ini melihat lebih dalam pesan teks historis dengan menerapkan berbagai teknik pembelajaran mesin. Tujuan dari penelitian ini adalah untuk menerapkan teknik Natural Language Processing (NLP) untuk mengidentifikasi tren komunikasi, mengevaluasi efektivitas proses yang ada, dan untuk memberikan wawasan dari data historis.
Metodologi
Untuk analisis data, saya menggunakan Python sebagai bahasa pemrograman bersama dengan berbagai perpustakaan perangkat lunak seperti pandas, math, numpy, sklearn, matplotlib dan lain-lain. Selain itu, saya telah menggunakan Natural Language Processing (NLP) yang merupakan pembelajaran mesin (ML) teknik yang membantu memahami, menafsirkan, dan memanipulasi bahasa manusia menggunakan kecerdasan buatan.
Eksplorasi Data
Fokusnya di sini adalah untuk mengeksplorasi kumpulan besar data tidak terstruktur dan mengungkap pola awal, karakteristik, dan hal menarik. Langkah ini tidak diharapkan untuk mengungkapkan seluruh informasi yang terdapat dalam kumpulan data, melainkan untuk membantu menciptakan gambaran luas tentang tren penting dan poin-poin utama untuk dipelajari secara lebih rinci.
Menemukan tren Pesan Masuk dan Keluar untuk Musim Semi dan Musim Panas
Kumpulan data saat ini berisi sejumlah kolom terbatas. Untuk mendapatkan jumlah pesan berdasarkan bulan, kita perlu mengekstrak tahun dan bulan dari kolom waktu.
df_text=pd.read_csv('../Data/clean_text.csv') df_text.info() <class 'pandas.core.frame.DataFrame'> RangeIndex: 62513 entries, 0 to 62512 Data columns (total 7 columns): message_type 62513 non-null object text 62513 non-null object time 62513 non-null object ID 62513 non-null object group_list 62513 non-null object term 62513 non-null object sent_by 62513 non-null object dtypes: object(7) memory usage: 3.3+ MB #Extracting year and month from 'time' column and append the dataframe with new columns. df_text['year'] = pd.DatetimeIndex(df_text['time']).year df_text['month'] = pd.DatetimeIndex(df_text['time']).month df_text.head()
Sekarang kita dapat menghitung jumlah pesan masuk dan keluar berdasarkan bulan.
# Getting the message count by message type and month # reset_index() gives a column for counting, after groupby uses year and category df_cnt = (df_text.reset_index() .groupby(['month','message_type'], as_index=False) .count() # rename isn't strictly necessary here, it's just for readability .rename(columns={'index':'count'}) ) #sorting the values by month df_cnt.sort_values(by = 'month', ascending = True)
Sekarang saatnya menggunakan matplotlibuntuk menyajikan data.
import matplotlib.pyplot as plt df_all_cnt =df_cnt #adding month name for better presentation df_all_cnt['month_t'] = df_all_cnt['month'].apply(lambda x: calendar.month_abbr[x]) fig, ax = plt.subplots(figsize=(5, 3), dpi=150) # key gives the group name (i.e. category), data gives the actual values for key, data in df_all_cnt.groupby('message_type'): data.plot(x='month_t', y='count', ax=ax, label=key) # Hide the right and top spines ax.spines['right'].set_visible(False) ax.spines['top'].set_visible(False) #draw the grid ax.grid( linestyle='-', linewidth=0.2) ax.legend() ax.set_xlabel('Month') ax.set_ylabel('Nu. Of Messages') ax.set_title('In and Out Messages By Month - Both Programs')
Dengan cara yang sama, kita dapat menggunakan kolom lain dalam kumpulan data sebagai sumbu x dan y untuk mengisi berbagai jenis grafik guna memperlihatkan berbagai aspek dari kumpulan data yang sama.
Analisis Teks dengan NLP
NLP adalah metode yang sangat baik untuk menganalisis dan menafsirkan data tekstual seperti respon siswa. Ini adalah teknik ML yang digunakan mesin untuk memahami bahasa manusia seperti teks, ucapan, emoji, dan banyak digunakan di industri saat ini (yaitu Siri dan Alexa).
Membersihkan, menghilangkan stopword dan stemming
Penting untuk membersihkan data Anda dengan menghapus semua kata, simbol, dan teks yang tidak perlu yang tidak akan membantu Anda melakukan analisis yang berarti. Fungsi di bawah ini akan membantu kita membersihkan, menghapus stopwords tetapi kita juga memerlukan beberapa perpustakaan untuk membantu hal itu.
from nltk.corpus import stopwords nltk.download('stopwords') nltk.download('punkt') from gensim.parsing.preprocessing import STOPWORDS from gensim.parsing.preprocessing import remove_stopwords set(stopwords.words('english')) from nltk.tokenize import word_tokenize from contractions import contractions_dict import unicodedata def remove_punctuation(text): text = ''.join([i for i in text if not i.isdigit()]) return re.sub("[!@#$+%*:()/|,;:'-]", ' ', text) def removebrackets(text): return re.sub('[\(\[].*?[\)\]]', ' ', text) def remove_accented_chars(text): return unicodedata.normalize('NFKD', text).encode('ascii', 'ignore').decode('utf-8', 'ignore') def remove_special_chars(text, remove_digits=False): pattern = r'[^a-zA-Z0-9\s]' if not remove_digits else r'[^a-zA-Z\s]' return re.sub(pattern, '', text) def remove_stopwords(text): # text_tokens = word_tokenize(text) # text = remove_stopwords(text) from gensim.parsing.preprocessing import STOPWORDS all_stopwords_gensim = STOPWORDS.union(set(['thank', 'need', 'yes', 'okay'])) text_tokens = word_tokenize(text) tokens_without_sw = ' '.join([word for word in text_tokens if not word in all_stopwords_gensim]) return tokens_without_sw def stemming (text): ps = nltk.porter.PorterStemmer() return ' '.join([ps.stem(word) for word in text.split()]) stopword_list = stopwords.words('english') tokens = nltk.word_tokenize(text) tokens = [token.strip() for token in tokens] return ' '.join([token for token in tokens if token not in stopword_list]) def lemmatize(text): text = nlp(text) return ' '.join([word.lemma_ if word.lemma_ != '-PRON-' else word.text for word in text]) def expand_contractions(text, contraction_mapping=contractions_dict): contractions_pattern = re.compile('({})'.format('|'.join(contraction_mapping.keys())), flags=re.IGNORECASE|re.DOTALL) def expand_match(contraction): match = contraction.group(0) first_char = match[0] expanded_contraction = contraction_mapping.get(match)\ if contraction_mapping.get(match)\ else contraction_mapping.get(match.lower()) expanded_contraction = first_char+expanded_contraction[1:] return expanded_contraction expanded_text = contractions_pattern.sub(expand_match, text) return re.sub("'", "", expanded_text)
Setelah membersihkan data, kami dapat mengisi kata cloud untuk analisis kami. Word Cloud adalah salah satu cara paling efektif untuk merepresentasikan data ini, yang menunjukkan pentingnya teks berdasarkan ukuran, kedalaman warna, dan ketebalan kata.
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator wc = WordCloud(stopwords=STOPWORDS,max_font_size=200, max_words=1000000, background_color="white", width=1000, height=1000).generate(' '.join(df_filtered['text_clean'])) plt.figure(figsize=(20,20)) plt.imshow(wc) plt.axis("off") plt.show()
Setelah mengisi kata cloud, Anda dapat mengidentifikasi teks lain yang tidak diperlukan untuk analisis Anda. Anda cukup memperluas perpustakaan stopwords saat ini dengan menambahkan kata-kata yang teridentifikasi sebagai berikut.
def clean_text_again(text): from gensim.parsing.preprocessing import STOPWORDS all_stopwords_gensim = STOPWORDS.union(set(['thank', 'need', 'yes', 'okay','ok','thanks','morning','hello','sure','hi', 'know', 'got','yesterday'])) text_tokens = word_tokenize(text) tokens_without_sw = [word for word in text_tokens if not word in all_stopwords_gensim] return ' '.join([word for word in text_tokens if not word in all_stopwords_gensim])
Word Cloud diperluas — Eksplorasi Ngram
Ngram hanyalah rangkaian kata n yang bersebelahan. Melihat n-gram yang paling sering dapat memberi kita pemahaman yang lebih baik tentang konteksnya.
Fungsi di bawah ini menyajikan kata-kata non-stop yang paling sering muncul dalam diagram batang.
import seaborn as sns def plot_top_non_stopwords_barchart(text): new= text.str.split() new=new.values.tolist() corpus=[word for i in new for word in i] counter=Counter(corpus) most=counter.most_common() x, y=[], [] for word,count in most[:40]: if (word not in stop): x.append(word) y.append(count) plt.figure(figsize=(15,8)) sns.barplot(x=y,y=x,palette="colorblind")
Namun, untuk memahami konteks kata-kata non-stop dan hubungannya; kita perlu mengisi grafik dengan kata-kata yang cenderung segera mengikutinya. Saya mengubah fungsi di atas menggunakan 3 kata langsung untuk menggambar Trigramsebagai berikut.
def plot_top_ngrams_barchart(text, n=3): #n is the number of immediate words you need. new= text.str.split() new=new.values.tolist() corpus=[word for i in new for word in i] def _get_top_ngram(corpus, n=None): vec = CountVectorizer(ngram_range=(n, n)).fit(corpus) bag_of_words = vec.transform(corpus) sum_words = bag_of_words.sum(axis=0) words_freq = [(word, sum_words[0, idx]) for word, idx in vec.vocabulary_.items()] words_freq =sorted(words_freq, key = lambda x: x[1], reverse=True) return words_freq[:10] top_n_bigrams=_get_top_ngram(text,n)[:10] x,y=map(list,zip(*top_n_bigrams)) sns.barplot(x=y,y=x)
Analisis Sentimen
Analisis sentimen adalah alat yang banyak digunakan dengan perangkat NLP yang mengklasifikasikan sentimen data tekstual seperti respons siswa dengan cara otomatis. Pertama, kita dapat mengetahui distribusi sentimen menggunakan histogram polaritas. Polaritas adalah bilangan floating-point yang terletak pada rentang -1 sampai 1 dimana 1 berarti pernyataan positif dan -1 berarti pernyataan negatif.
from textblob import TextBlob def plot_polarity_histogram(text): def polarity(text): return TextBlob(text).sentiment.polarity df_x = pd.DataFrame() polarity_score =text.apply(lambda x : polarity(x)) df_filtered['polarity_score']=df_filtered['text'].\ apply(lambda x : polarity(x)) polarity_score.hist()
Sentimen tersebut dapat kita analisa lebih lanjut untuk melihat sebaran sentimen positif, negatif, dan netral. Fungsi di bawah ini mengkategorikan sentimen dan menyajikan plot batang.
from textblob import TextBlob import matplotlib.pyplot as plt from nltk.sentiment.vader import SentimentIntensityAnalyzer import nltk def sentiment_vader(text, sid): ss = sid.polarity_scores(text) ss.pop('compound') return max(ss, key=ss.get) def sentiment_textblob(text): x = TextBlob(text).sentiment.polarity if x<0: return 'Negative' elif x==0: return 'Neutral' else: return 'Positive' def sentiment_x(x): if x<0: return 'Negative' elif x==0: return 'Neutral' else: return 'Positive' def plot_sentiment_barchart(text, method): if method == 'TextBlob': sentiment = text.map(lambda x: sentiment_textblob(x)) elif method == 'Vader': nltk.download('vader_lexicon') sid = SentimentIntensityAnalyzer() sentiment = text.map(lambda x: sentiment_vader(x, sid=sid)) else: raise ValueError('Textblob or Vader') df_filtered['polarity']=df_filtered['polarity_score'].\ apply(lambda x : sentiment_x(x)) plt.figure(figsize=(5, 2), dpi=100) plt.bar(sentiment.value_counts().index, sentiment.value_counts())
Teknologi analisis sentimen masih dalam tahap awal. Oleh karena itu, prediksi harus dievaluasi sesuai dan dengan campur tangan manusia. Namun dengan sejumlah besar data yang bersih dan diberi label, jaringan saraf yang cukup besar akan semakin akurat dan akan menjadi alat yang hebat dalam jangka panjang.