ABONAMENTE VIDEO REDACȚIA
RO
EN
NOU
Numărul 149
Numărul 148 Numărul 147 Numărul 146 Numărul 145 Numărul 144 Numărul 143 Numărul 142 Numărul 141 Numărul 140 Numărul 139 Numărul 138 Numărul 137 Numărul 136 Numărul 135 Numărul 134 Numărul 133 Numărul 132 Numărul 131 Numărul 130 Numărul 129 Numărul 128 Numărul 127 Numărul 126 Numărul 125 Numărul 124 Numărul 123 Numărul 122 Numărul 121 Numărul 120 Numărul 119 Numărul 118 Numărul 117 Numărul 116 Numărul 115 Numărul 114 Numărul 113 Numărul 112 Numărul 111 Numărul 110 Numărul 109 Numărul 108 Numărul 107 Numărul 106 Numărul 105 Numărul 104 Numărul 103 Numărul 102 Numărul 101 Numărul 100 Numărul 99 Numărul 98 Numărul 97 Numărul 96 Numărul 95 Numărul 94 Numărul 93 Numărul 92 Numărul 91 Numărul 90 Numărul 89 Numărul 88 Numărul 87 Numărul 86 Numărul 85 Numărul 84 Numărul 83 Numărul 82 Numărul 81 Numărul 80 Numărul 79 Numărul 78 Numărul 77 Numărul 76 Numărul 75 Numărul 74 Numărul 73 Numărul 72 Numărul 71 Numărul 70 Numărul 69 Numărul 68 Numărul 67 Numărul 66 Numărul 65 Numărul 64 Numărul 63 Numărul 62 Numărul 61 Numărul 60 Numărul 59 Numărul 58 Numărul 57 Numărul 56 Numărul 55 Numărul 54 Numărul 53 Numărul 52 Numărul 51 Numărul 50 Numărul 49 Numărul 48 Numărul 47 Numărul 46 Numărul 45 Numărul 44 Numărul 43 Numărul 42 Numărul 41 Numărul 40 Numărul 39 Numărul 38 Numărul 37 Numărul 36 Numărul 35 Numărul 34 Numărul 33 Numărul 32 Numărul 31 Numărul 30 Numărul 29 Numărul 28 Numărul 27 Numărul 26 Numărul 25 Numărul 24 Numărul 23 Numărul 22 Numărul 21 Numărul 20 Numărul 19 Numărul 18 Numărul 17 Numărul 16 Numărul 15 Numărul 14 Numărul 13 Numărul 12 Numărul 11 Numărul 10 Numărul 9 Numărul 8 Numărul 7 Numărul 6 Numărul 5 Numărul 4 Numărul 3 Numărul 2 Numărul 1
×
▼ LISTĂ EDIȚII ▼
Numărul 32
Abonament PDF

Analiza sentimentelor şi complexitatea opiniilor online

Cosmin Gabriel Popa
SA R&D Osprov Team
@Hewlett Packard



PROGRAMARE

Dacă ai trăi într-o lume unde opinia ta contează, ai încerca să schimbi ceva? Fără îndoială că opiniile sunt o prezență constantă în viața fiecăruia: recomandările, recenziile, sunt doar câteva din mijloacele folosite pentru a influența viitoarele decizii. În era vitezei, când multitudinea opțiunilor te inhibă, opiniile sunt cele ce te pot determina în a lua o decizie rapidă când ești sub lumina reflectorului. Dar să presupunem că am putea evalua totul în termeni de pro sau contra, ar fi deciziile noastre mai corecte? Sau nu e chiar atât de simplu?

Sentiment Analysis sau Opinion Mining este o ramură a domeniului de Natural Language Processing (NLP) ce se ocupă cu studiul opiniilor, sentimentelor, evaluărilor, atitudinilor, emoțiilor și caracteristicele acestora, direcționate spre anumite entități precum produse, organizații, indivizi, evenimente, etc. . Nu a existat un interes deosebit pentru această disciplină înainte de anul 2000, dar odată cu răspândirea aplicațiilor comerciale (online sau offline), perspectiva asupra analizei opiniilor s-a schimbat în mod radical. E și pentru prima dată în istorie când există o bază de date dogmatică consistentă, alcătuită cu ajutorul rețelelor de socializare. Nu e atât de surprinzătoare schimbarea de perspectivă ținând cont de aplicațiile sale în domenii politice, sociologice, economice ș.a. și de popularitatea de care se bucură socializarea online în zilele noastre.

Enunțarea problemei

Să ne întoarcem totuși la întrebarea inițială. Vom lua drept exemplu filmele și o serie de recenzii asupra acestora. Vom împărți astfel opiniile în două categorii, după cum am stabilit inițial: pozitiv (pro) și negativ (contra). Astfel putem enunța întrebarea: dacă ar exista o recenzie negativă despre actorul principal și una pozitivă despre regizor, ai mai viziona filmul? Ai mai avea nevoie de încă o părere despre film? Cum poți determina dacă următoarea opinie va fi una pozitivă sau una negativă? Și cum te-ar putea influența aceasta?

Există diferite metode de analiză depinzând de granularitatea cu care se abordează problema: analiza per document (Document Analysis) care determină dacă un întreg document exprimă o opinie pozitivă sau negativă; analiza per propoziție (Sentence Analysis) care stabilește dacă o propoziție este pozitivă, negativă sau neutră; analiza per entitate sau aspect (Entity and Aspect or Feature Analysis) care precizează asupra cărei entități se adresează opinia și polaritatea opiniei.

Soluția

Există două metode de clasificare a opiniilor: aceea prin antrenarea unei rețele neuronale (Supervised Learning) și aceea ce nu implică o astfel de antrenare (Unsupervised Learning). Simplificând analiza la nivelul propoziției presupunând că avem la dispoziție doar documente cu tentă pozitivă sau negativă, vom aborda o soluție prin Supervised Learning cu ajutorul platformei NLTK (Natural Language Toolkit).

{python code}
from nltk.corpus import movie_reviews
positive_ids = movie_reviews.fileids('pos')
negative_ids = movie_reviews.fileids('neg')
{/python code}

După cum se poate observa corpusul de "movie_reviews" conține recenzii de filme deja segregate în cele două categorii stabilite inițial. Din acestea vom extrage cuvinte drept informațiile de care vom depinde pe viitor.

{python code}
positive_data = [movie_reviews.words(fileids=[f]) for f in positive_ids]
negative_data = [movie_reviews.words(fileids=[f]) for f in negative_ids]
{/python code}

Suntem în punctul unde trebuie să decidem cu ce vor fi reprezentate instanțele în momentul în care vom antrena rețeaua neuronală. Pentru simplitate vom alege drept caracteristică cuvintele cele mai frecvente din corpusul specific. Se implementează astfel o funcție care determină frecvența fiecărui cuvânt pentru cele două categorii, împreună și diferențial.

{python code}
import itertools
from nltk import FreqDist, ConditionalFreqDist
def buildFreqDistribution(positiveWords, negativeWords):
  word_fd = FreqDist()
  cond_word_fd = ConditionalFreqDist()
  for word in list(itertools.chain(*positiveWords)):
   word_fd[word.lower()] += 1
   cond_word_fd['positive'][word.lower()] += 1
   for word in list(itertools.chain(*negativeWords)):
     word_fd[word.lower()] += 1
  cond_word_fd['negative'][word.lower()] += 1
  return (word_fd, cond_word_fd)
{/python code}

Bazându-ne pe frecvențele calculate anterior, vom construi un dicționar care va conține scorul fiecărui cuvânt. Funcția "BigramAssocMeasures" calculează relevanța cuvântului respectiv în contextul în care se află acesta, returnând o valoare reprezentativă.

{python code}
from nltk import BigramAssocMeasures
def buildWordsScores(word_fd, cond_word_fd, total_word_count):

 word_scores = {}
  for word, freq in word_fd.items():
  positive_score = BigramAssocMeasures.chi_sq(cond_word_fd['positive'][word], (freq, cond_word_fd['positive'].N()), total_word_count)

  negative_score = BigramAssocMeasures.chi_sq(cond_word_fd['negative'][word], 
 (freq, cond_word_fd['negative'].N()),total_word_count)

  word_scores[word] = positive_score + negative_score
  return word_scores
{/python code}

Se implementează și funcțiile care vor filtra informațiile relevante pentru antrenarea rețelei neuronale.

{python code}
def getFeatures(label, data, best_words):
  features = []
  for feat in data:
  words = [selectBestWords(feat, best_words), label]
  features.append(words)
return features

def selectBestWords(words, best_words):
  return dict([(word, True) for word in words if word in best_words])

def findBestWords(scores, number):
  best_vals = sorted(scores.items(), key=lambda w_s: 
    w_s[1], reverse=True)[:number]
  best_words = set([w for w, s in best_vals])
  return best_words
{/python code}

Tot ce mai rămâne este să le punem cap la cap. Cu informațiile extrase până acum vom antrena rețeaua neuronală reprezentată de NaiveBayesClassifier. Pentru simplitate vom reveni la platforma NTLK utilizând algoritmul său standard.

{python code}
(word_fd, cond_word_fd) = buildFreqDistribution(positive_data, negative_data)
total_word_count = cond_word_fd['positive'].N() + cond_word_fd['negative'].N()

word_scores = buildWordsScores(word_fd, cond_word_fd, total_word_count)

best_words = findBestWords(word_scores, 1000)
positive_features = getFeatures('positive', positive_data, best_words)

negative_features = getFeatures('negative', negative_data, best_words)

classifier = NaiveBayesClassifier.train(positive_features + negative_features)
classifier.show_most_informative_features(10)
{/python code}

Se pare că dispunem acum de un mecanism ce poate determina cu o oarecare precizie dacă o recenzie este pozitivă sau negativă. Să luam spre exemplu următoarea recenzie la un film cu Kevin Costner : "Once again Mr. Costner has dragged out a movie for far longer than necessary. Aside from the terrific sea rescue sequences, of which there are very few I just did not care about any of the characters [...]" O recenzie ce, la prima vedere, pare a fi una negativă.

{python code}
features = selectBestWords(words_in_review, best_words)
print(classifier.classify(features))
{/python code}

Se dovedește a fi pozitivă cu o diferență de scor de _1.4. Dacă adaugăm și restul recenziei : **"[...] Most of us have ghosts in the closet, and Costner's character are realized early on, and then forgotten until much later, by which time I did not care. The character we should really care about is a very cocky, overconfident Ashton Kutcher. The problem is he comes off as a kid who thinks he's better than anyone else around him and shows no signs of a cluttered closet."_, aceasta reiese a fi negativă cu o diferență de scor de 0.9**.

Studiu de caz

Utilizând algoritmul SVM (Support Vector Machines) în paralel cu algoritmul NaiveBayesClassifier și testând cei doi algoritmi pe o baza de date ajungând la peste 6 milioane de cuvinte, am obținut următoarele grafice. Odată cu creșterea numărului de entități extrase din text și folosit în antrenarea rețelelor neuronale, se pot observa diferențe de acuratețe generală și de clasificare.

Se poate observa cum precizia algoritmului rămâne constantă și în creștere până la un punct de plafonare în jurul valorii aproximative de : 0.81%. Chiar dacă numărul de features (entități) crește, acuratețea va oscila în jurul valorii de plafonare. Totuși, instabilitatea în cazul algoritmului NaiveBayesClassifier se poate observa mai bine în ultimul grafic. Algoritmul SVM se dovedește a fi mai fiabil în acest caz.

Concluzii

Se pare ca nu e atât de simplu. Am fost păcăliți chiar de propriul nostru algoritm. Totuși, nu există o metodă standardizată de determinare a "sentimentului" degajat de o opinie. Până și prin simplificarea radicală a problemei nu s-a putut ajunge la o acuratețe impresionantă, nici măcar apropiată de 95%. Există diferite metode și diferiți algoritmi ce se pot folosi în Supervised sau Unsupervised Learning, dar soluția cea mai bună este combinarea acestor două mari metode. Desigur o importanță deosebită o poartă bazele de date folosite, metodele implementate, corpusul de test, toate acestea având necesitatea de a corespunde intenției dezvoltatorului. Opiniile cumulate pot determina valoarea unui produs, a unui individ, a unei idei sau a unui eveniment. Cu opinii ești bombardat în fiecare zi pe orice device, pe orice aplicație, pe orice pagină Web, pe orice stradă. În final, contează sau nu părerea ta? Eu zic: Da!

NUMĂRUL 149 - Development with AI

Sponsori

  • Accenture
  • BT Code Crafters
  • Accesa
  • Bosch
  • Betfair
  • MHP
  • BoatyardX
  • .msg systems
  • P3 group
  • Ing Hubs
  • Cognizant Softvision
  • Colors in projects

Cosmin Gabriel Popa a mai scris