Doğal Dil İşleme (NLP) ile Sentiment (Duygu) Analizi Tespiti

Herkese Selam,

Bu yazıda doğal dil işleme tekniklerini kullanarak basit bir sentiment analizi uygulaması geliştireceğim. Umarım farkındalık anlamında faydalı bir yazı olur.

Son yıllarda yapay zeka konusundaki gelişmeleri takiben doğal dil işleme tabanlı geliştirilen yapay zeka uygulamalarının önemi ve sayısı gün geçtikçe artmakta.  Bu konuda geliştirilen uygulamalar bir çok işte insan gücünü ortadan kaldırarak daha hızlı ve daha doğru çalışan alt yapılar kullanmamıza olanak sağlayacaktır. Doğal dil işleme ile geliştirilen yaygın örnek uygulamalar ise şu alanlarda karşımıza çıkmakta.

  • Metinleri Sınıflandırma (Spam Detector, Haber Konularının Tespiti)
  • Sentiment Analizi (Duygu analizi)
  • Yazar Tespiti / Yazar Tanıma
  • Makine Çevirisi (Google Translate, Amazon Translate..)
  • Chatbot

Sentiment analizi doğal dil işleme teknikleri ile geliştirilen ve karşımıza en sık çıkan problemlerden bir tanesi. Sentiment analizi ile yazılan bir metnin hangi duygu durumu ile yazıldığına karar verebiliyoruz.

Sosyal medya kullanımın yaygınlaşması ile birlikte insanların sosyal medya üzerinden paylaştıkları görüşlerinin analiz edilme ihtiyacı gün geçtikçe artmakta. Sosyal medya üzerinden akan verinin hacmi düşünüldüğünde bu işi insan gücü ile yapılabilmesi oldukça güç bir iştir. Bu nedenle insanların yazdıkları olumlu veya olumsuz yorumları hızlı bir şekilde algılayıp aksiyon alabilen uygulamalara ihtiyaç her geçen gün artmakta. Bu yazıda bu konuya basit bir giriş yapabileceğimiz bir benchmark uygulaması geliştireceğiz.

Öncelikle sentiment analizi yapacağımız veri setini ile ilgili bilgi verelim.

Veri Seti : Sentiment Labelled Sentences Data Set 

Kaynak : UCI Machine Learning Libarary

İçerik : Bu veri seti 3 farklı internet sitesi (Amazon, Yelp, Imdb) üzerinden toplanmış kullanıcı yorumları ile oluşturulmuştur. Bu yorumlar restoran, film ve ürün değerlendirmelerinden oluşmaktadır. Veri setindeki her bir kayıt iki farklı duygu ile etiketlenmiştir. Bunlar  1: Olumlu/Pozitif   2:Olumsuz/Negatif

Yukarıda detaylarını vermiş olduğumuz veri setini kullanarak örnek bir sentiment analizi modeli oluşturacağız.

Bu modeli kullanma için kuracağımız makine öğrenmesi modelini python programlama dili ile sklearn ve nltk kütüphanesini kullanarak yapacağız.

Şimdi kodumuzu yazma kısmına geçebiliriz.

Öncelikle Kullanacağımız kütüphaneleri import edelim.

import pandas as pd
import numpy as np
import pickle
import sys
import os
import io
import re
from sys import path
import numpy as np
import pickle
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer
import matplotlib.pyplot as plt
from string import punctuation, digits
from IPython.core.display import display, HTML
from nltk.corpus import stopwords
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from nltk.tokenize import RegexpTokenizer

Şimdi verimizi yükleyelim ve görüntüleyelim.

#Amazon Data
input_file = "../data/amazon_cells_labelled.txt"
amazon = pd.read_csv(input_file,delimiter='\t',header=None)
amazon.columns = ['Sentence','Class']

#Yelp Data
input_file = "../data/yelp_labelled.txt"
yelp = pd.read_csv(input_file,delimiter='\t',header=None)
yelp.columns = ['Sentence','Class']

#Imdb Data
input_file = "../data/imdb_labelled.txt"
imdb = pd.read_csv(input_file,delimiter='\t',header=None)
imdb.columns = ['Sentence','Class']


#combine all data sets
data = pd.DataFrame()
data = pd.concat([amazon, yelp, imdb])
data['index'] = data.index

data

Evet veriyi yükledik ve görüntüledik. Şimdi ise veri ile ilgili istatistiklere bakalım.

#Total Count of Each Category
pd.set_option('display.width', 4000)
pd.set_option('display.max_rows', 1000)
distOfDetails = data.groupby(by='Class', as_index=False).agg({'index': pd.Series.nunique}).sort_values(by='index', ascending=False)
distOfDetails.columns =['Class', 'COUNT']
print(distOfDetails)

#Distribution of All Categories
plt.pie(distOfDetails['COUNT'],autopct='%1.0f%%',shadow=True, startangle=360)
plt.show()

Görüldüğü üzere veri seti oldukça dengeli. Pozitif ve negatif sınıfa ait neredeyse eşit sayıda örnek bulunmakta.

Şimdi veri setini model içerisinde kullanmadan önce, metini temizlemek için bir kaç işlem yapalım.

#Text Preprocessing
columns = ['index','Class', 'Sentence']
df_ = pd.DataFrame(columns=columns)

#lower string
data['Sentence'] = data['Sentence'].str.lower()

#remove email adress
data['Sentence'] = data['Sentence'].replace('[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_.]+', '', regex=True)

#remove IP address
data['Sentence'] = data['Sentence'].replace('((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}', '', regex=True)

#remove punctaitions and special chracters
data['Sentence'] = data['Sentence'].str.replace('[^\w\s]','')

#remove numbers
data['Sentence'] = data['Sentence'].replace('\d', '', regex=True)

#remove stop words
for index, row in data.iterrows():
    word_tokens = word_tokenize(row['Sentence'])
    filtered_sentence = [w for w in word_tokens if not w in stopwords.words('english')]
    df_ = df_.append({"index": row['index'], "Class":  row['Class'],"Sentence": " ".join(filtered_sentence[0:])}, ignore_index=True)

data = df_

Verinin ön temizliğini yaparak model içerisinde kullanmaya hazır hale getirdik. Şimdi modelimizi oluşturmadan önce verimizi test (%10) ve eğitim (%90) olacak şekilde bölme işlemini yapalım.

X_train, X_test, y_train, y_test = train_test_split(data['Sentence'].values.astype('U'),data['Class'].values.astype('int32'), test_size=0.10, random_state=0)
classes  = data['Class'].unique()

Artık eğitim verimizi kullanarak modelimizi oluşturabiliriz. Modeli oluştururken vectorizer olarak TF-IDF, sınıflandırıcı olarak ise Stochastic Gradient Descend algoritması kullanacağım. Bu metodları ve metod içerisindeki parametreleri grid search kullanarak bulduk (Bu yazıda grid search’ten bahsetmeyeceğim).

from sklearn.metrics import confusion_matrix
from sklearn.model_selection import cross_val_score
from sklearn.metrics import accuracy_score
from sklearn.neural_network import MLPClassifier
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import SGDClassifier


#grid search result
vectorizer = TfidfVectorizer(analyzer='word',ngram_range=(1,2), max_features=50000,max_df=0.5,use_idf=True, norm='l2') 
counts = vectorizer.fit_transform(X_train)
vocab = vectorizer.vocabulary_
classifier = SGDClassifier(alpha=1e-05,max_iter=50,penalty='elasticnet')
targets = y_train
classifier = classifier.fit(counts, targets)
example_counts = vectorizer.transform(X_test)
predictions = classifier.predict(example_counts)

Modelimiz oluştu şimdi test datası ile modelimizi test edip accuracy, precision, recall ve f1 sonuçlarına bakalım.

from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import classification_report

#Model Evaluation
acc = accuracy_score(y_test, predictions, normalize=True)
hit = precision_score(y_test, predictions, average=None,labels=classes)
capture = recall_score(y_test, predictions, average=None,labels=classes)

print('Model Accuracy:%.2f'%acc)
print(classification_report(y_test, predictions))
Model Accuracy:0.83
             precision    recall  f1-score   support

          0       0.83      0.84      0.84       139
          1       0.84      0.82      0.83       136

avg / total       0.83      0.83      0.83       275

Görüldüğü üzere oluşturduğumuz modelin başarısı %83 çıktı. Şimdi modelimizin tahminlerinin ne kadar doğru olduğunu daha net görebileceğimiz confusion matrix’e bakalım.

#source: https://www.kaggle.com/grfiv4/plot-a-confusion-matrix
import itertools
def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    """
    This function prints and plots the confusion matrix.
    Normalization can be applied by setting `normalize=True`.
    """
    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
        #print("Normalized confusion matrix")
    else:
        print()

    plt.imshow(cm, interpolation='nearest', cmap=cmap, aspect='auto')
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)

    fmt = '.2f' if normalize else 'd'
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j], fmt),
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.figure(figsize=(150,100))
# Compute confusion matrix
cnf_matrix = confusion_matrix(y_test, predictions,classes)
np.set_printoptions(precision=2)

class_names = range(1,classes.size+1)

# Plot non-normalized confusion matrix
plt.figure()
plot_confusion_matrix(cnf_matrix, classes=class_names,title='Confusion matrix, without normalization')

classInfo = pd.DataFrame(data=[])
for i in range(0,classes.size):
    classInfo = classInfo.append([[classes[i],i+1]],ignore_index=True)

classInfo.columns=['Category','Index']
classInfo

Evet bu çalışma ile baştan uca bir doğal dil işleme projesi geliştirdik. Yazının en başında da söylemiş olduğum gibi, kurduğumuz model bir başlangıç modeli olarak alınarak daha iyi modellerin önü açılabilir. Bu yazımızın amacı doğal dil işlemeye giriş sayılabilecek bir uygulama geliştirmekte. Umarım farkındalık anlamında faydalı bir yazı olmuştur.

Advertisements

About ... from Emrah METE

Bilgisayar Mühendisi
This entry was posted in Root, Uncategorized and tagged , , , , , , , , , . Bookmark the permalink.

2 Responses to Doğal Dil İşleme (NLP) ile Sentiment (Duygu) Analizi Tespiti

  1. Pingback: Sklearn ile Machine Learning Modellerinin Saklanması, Yüklenmesi ve Kullanılması | Emrah METE

  2. ufuk says:

    merhaba veriyi yüklerken sorunla karşılaşıyorum.
    Traceback (most recent call last):
    File “C:/Users/ufuk/deneme12323/denem123.py”, line 26, in
    amazon = pd.read_csv(input_file,delimiter=’\t’,header=None)
    File “C:\Users\ufuk\Anaconda3\lib\site-packages\pandas\io\parsers.py”, line 702, in parser_f
    return _read(filepath_or_buffer, kwds)
    File “C:\Users\ufuk\Anaconda3\lib\site-packages\pandas\io\parsers.py”, line 429, in _read
    parser = TextFileReader(filepath_or_buffer, **kwds)
    File “C:\Users\ufuk\Anaconda3\lib\site-packages\pandas\io\parsers.py”, line 895, in __init__
    self._make_engine(self.engine)
    File “C:\Users\ufuk\Anaconda3\lib\site-packages\pandas\io\parsers.py”, line 1122, in _make_engine
    self._engine = CParserWrapper(self.f, **self.options)
    File “C:\Users\ufuk\Anaconda3\lib\site-packages\pandas\io\parsers.py”, line 1853, in __init__
    self._reader = parsers.TextReader(src, **kwds)
    File “pandas/_libs/parsers.pyx”, line 387, in pandas._libs.parsers.TextReader.__cinit__
    File “pandas/_libs/parsers.pyx”, line 705, in pandas._libs.parsers.TextReader._setup_parser_source
    FileNotFoundError: [Errno 2] File b’../dataset/amazon_cells_labelled.txt’ does not exist: b’../dataset/amazon_cells_labelled.txt’

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.