Metindeki Kelimelerin Mutlak ve Ağırlıklandırılmış Sıklığı
Bu eğitimde, metin madenciliğinde mutlak ve ağırlıklandırılmış kelime sıklığını ve bunu defaultdict ile pandas DataFrame’leri kullanarak nasıl hesaplayacağınızı öğreneceksiniz.
Metin madenciliğinde önemli metrik kümelerinden biri, belirli bir metin dokümanları külliyatındaki kelimelerin (veya herhangi bir token’ın) sıklığıyla ilgilidir. Ancak, her belgenin belgeye ait belirli bir niteliği tanımlayan sayısal bir değerle ilişkilendirildiği durumlarda, ilave metrik kümeleri de kullanabilirsiniz.
Bazı örnekler:
Tweet’ler ve bunların aldığı etkileşim sayıları.
URL’ler ve sayfa görüntülemeleri ile hemen çıkma sayıları.
Film adları ve gişe geliri.
Anahtar kelimeler ve gösterimler, tıklamalar, dönüşümler.
Bu eğitimde,
Önce, bir belge külliyatında kelimelerin mutlak ve ağırlıklandırılmış geçiş sıklığını hesaplayan ve karşılaştıran basit bir fonksiyon oluşturma sürecinden geçeceksiniz. Bu, bazen ilk on değere bakarak net olmayan gizli eğilimleri ve toplamları ortaya çıkarabilir. Ayrıca çoğu zaman mutlak kelime sıklığından da farklı olabilirler.
Ardından, gerçek bir veri kümesini (film adları ve gişe geliri) görecek ve gizli eğilimleri keşfetmeyi umacağız. Küçük bir ipucu: aşk bir şekilde karşımıza çıkacak!
Programlama dili olarak Python kullanacak ve işin ağır kısmı için collections modülünün defaultdict veri yapısından, nihai çıktıyı yönetmek için de pandas DataFramelerinden yararlanacaksınız.
Mutlak ve Ağırlıklandırılmış Kelime Sıklığı: Giriş
İki tweet’iniz olduğunu ve içerikleri ile gösterim (görüntüleme) sayılarının aşağıdaki gibi olduğunu varsayalım:
Tweet Metni
Görüntüleme
spain
800
france
200
Basit analizi yapmak ve kelimelerinizin 'france' ve 'spain' arasında 50:50 bölündüğünü bulmak kolaydır. Çoğu durumda elinizde yalnızca bu olur ve sadece kelimelerin mutlak sıklığını ölçebilir, bazı ilişkileri çıkarsamaya çalışabilirsiniz. Bu örnekte ise her belgeye dair bazı verileriniz var.
Burada ağırlıklandırılmış sıklık belirgin şekilde farklıdır ve dağılım 80:20’dir. Başka bir deyişle, tweet’lerinizde 'spain' ve 'france' birer kez görünse de, okuyucularınızın gözünde ilki 800, ikincisi 200 kez görünmüştür. Büyük fark!
defaultdict kullanarak Basit Kelime Sıklığı
Şimdi benzer bir belge kümesi için biraz daha kapsamlı şu örneği ele alalım:
Belge
Görüntüleme
france
200
spain
180
spain beaches
170
france beaches
160
spain best beaches
160
Şimdi belgeler arasında döngü kuruyor, onları kelimelere ayırıyor ve her kelimenin kaç kez geçtiğini sayıyorsunuz:
from collections import defaultdict
import pandas as pd
text_list =['france','spain','spain beaches','france beaches','spain best beaches']
word_freq = defaultdict(int)for text in text_list:for word in text.split():
word_freq[word]+=1
pd.DataFrame.from_dict(word_freq, orient='index') \
.sort_values(0, ascending=False) \
.rename(columns={0:'abs_freq'})Altyapı:
abs_freq
spain
3
beaches
3
france
2
best
1
Yukarıdaki döngüde ilk satır, text_list üzerinde birer birer gezinir. İkinci satır (her belge için), öğeyi boşluk karakterine göre bölerek (başka bir karakter de olabilirdi ('-', ',', '_', vb.)) kelimeleri arasında döngü yapar.
word_freq[word]’a bir değer atamaya çalıştığınızda iki olası senaryo vardır:
word anahtarı vardır: bu durumda atama yapılır (bir eklenir)
word anahtarı word_freq içinde yoktur; bu durumda defaultdict, ilk tanımlandığında kendisine atanan varsayılan fonksiyonu çağırır; burada bu fonksiyon int’tir.
int çağrıldığında sıfır döndürür. Artık anahtar vardır, değeri sıfırdır ve değerine 1 eklenerek atama yapılmaya hazırdır.
İlk tabloda üst sıradaki kelime 'france' iken, her belgedeki tüm kelimeler sayıldıktan sonra 'spain' ve 'beaches'in birincilikte başa baş olduğunu görüyoruz. Bu, özellikle üzerinde çalıştığınız belge listesi onlarca ya da yüz binlerce öğeden oluştuğunda gizli eğilimleri ortaya çıkarmada önemlidir.
Ağırlıklandırılmış Kelime Sıklığı
Artık külliyattaki her kelimenin geçişlerini saydığınıza göre, ağırlıklandırılmış sıklığı görmek istiyorsunuz. Yani, kelimelerin okuyucularınıza kaç kez göründüğünü, sizin onları kaç kez kullandığınıza kıyasla görmek istiyorsunuz.
İlk tabloda kelimelerin mutlak sıklığı 'spain' ve 'france' arasında eşit dağılmıştı, ancak 'spain' bariz biçimde daha fazla ağırlığa sahipti; çünkü değeri 800 iken 'france' için 200’dü.
Peki ikinci, biraz daha karmaşık tablo için ağırlıklandırılmış kelime sıklığı ne olurdu?
Hadi bulalım!
Yukarıda kullandığınız kodun bir kısmını, bazı eklemelerle yeniden kullanabilirsiniz:
# default value is now a list with two ints
word_freq = defaultdict(lambda:[0,0])# the `views` column you had in the first DataFrame
num_list =[200,180,170,160,160]# looping is now over both the text and the numbersfor text, num inzip(text_list, num_list):for word in text.split():# same as before
word_freq[word][0]+=1# new line, incrementing the numeric value for each word
word_freq[word][1]+= num
columns ={0:'abs_freq',1:'wtd_freq'}
abs_wtd_df = pd.DataFrame.from_dict(word_freq, orient='index') \
.rename(columns=columns) \
.sort_values('wtd_freq', ascending=False) \
.assign(rel_value=lambda df: df['wtd_freq']/ df['abs_freq']) \
.round()
abs_wtd_df.style.background_gradient(low=0, high=.7, subset=['rel_value'])Altyapı:
abs_freq
wtd_freq
rel_value
spain
3
510
170
beaches
3
490
163
france
2
360
180
best
1
160
160
Bazı gözlemler:
'france' genel olarak en yüksek ifade olmasına rağmen, ağırlıklandırılmış sıklığı dikkate aldığınızda 'spain' ve 'beaches' daha baskın görünüyor.
rel_value, her kelimenin geçiş başına değerini elde etmek için yapılan basit bir bölmedir.
rel_value’a bakınca, 'france' wtd_freq metriğinde oldukça düşük olsa da, geçiş başına değeri yüksek olduğu için potansiyel barındırdığı görülüyor. Bu, örneğin 'france' kapsamındaki içeriklerinizi artırmayı düşündürebilir.
Ayrıca, toplamın çoğunluğunu kaç kelimenin oluşturduğuna daha iyi bir perspektiften bakmak için her tür sıklığın yüzdelerini ve kümülatif yüzdelerini gösteren bazı diğer metrikleri de eklemek isteyebilirsiniz:
Daha fazla analiz yapılabilir ve daha fazla veriyle genellikle daha çok sürprizle karşılaşırsınız.
Peki bu, gerçek verilerle gerçek dünyada nasıl görünür?
Film adlarına bakacak, başlıklarda en çok hangi kelimelerin kullanıldığını —yani mutlak sıklığı— ve en çok hangi kelimelerin gelirle ilişkilendirildiğini, yani ağırlıklandırılmış sıklığı göreceksiniz.
Boxoffice Mojo 15.000’den fazla filmi, ilgili gişe geliri ve sıralamalarıyla birlikte listeliyor. requests ve BeautifulSoup kullanarak veriyi kazıyarak başlayın — İsterseniz Boxoffice Mojo’yu burada şimdiden keşfedebilirsiniz:
import requests
from bs4 import BeautifulSoupAltyapı:
final_list =[]for i inrange(1,156):ifnot i%10:print(i)
page ='http://www.boxofficemojo.com/alltime/domestic.htm?page='+str(i)+'&p=.htm'
resp = requests.get(page)
soup = BeautifulSoup(resp.text,'lxml')# trial and error to get the exact positions
table_data =[x.text for x in soup.select('tr td')[11:511]]# put every 5 values in a row
temp_list =[table_data[i:i+5]for i inrange(0,len(table_data[:-4]),5)]for temp in temp_list:
final_list.append(temp)Altyapı:
Bazı sayısal değerlerde özel karakterler ($, , ve ^) yer aldığını ve bazı değerlerin aslında N/A olduğunu göreceksiniz. Dolayısıyla bunları dönüştürmeniz gerekir:
na_year_idx =[i for i, x inenumerate(final_list)if x[4]=='n/a']# get the indexes of the 'n/a' values
new_years =[1998,1999,1960,1973]# got them by checking onlineprint(*[(i, x)for i, x inenumerate(final_list)if i in na_year_idx], sep='\n')print('new year values:', new_years)Altyapı:
(8003,['8004','Warner Bros. 75th Anniversary Film Festival','WB','$741,855','n/a'])(8148,['8149','Hum Aapke Dil Mein Rahte Hain','Eros','$668,678','n/a'])(8197,['8198','Purple Moon (Re-issue)','Mira.','$640,945','n/a'])(10469,['10470','Amarcord','Jan.','$125,493','n/a'])newyearvalues:[1998,1999,1960,1973]Altyapı:
for na_year, new_year inzip(na_year_idx, new_years):
final_list[na_year][4]= new_year
print(final_list[na_year], new_year)Altyapı:
['8004','Warner Bros. 75th Anniversary Film Festival','WB','$741,855',1998]1998['8149','Hum Aapke Dil Mein Rahte Hain','Eros','$668,678',1999]1999['8198','Purple Moon (Re-issue)','Mira.','$640,945',1960]1960['10470','Amarcord','Jan.','$125,493',1973]1973Altyapı:
Şimdi listeyi uygun adlarla sütunlarını adlandırıp, istediğiniz veri türlerine dönüştürerek bir pandas DataFrame’ine çeviriyorsunuz.
import re
regex ='|'.join(['\$',',','\^'])
columns =['rank','title','studio','lifetime_gross','year']
boxoffice_df = pd.DataFrame({'rank':[int(x[0])for x in final_list],# convert ranks to integers'title':[x[1]for x in final_list],# get titles as is'studio':[x[2]for x in final_list],# get studio names as is'lifetime_gross':[int(re.sub(regex,'', x[3]))for x in final_list],# remove special characters and convert to integer'year':[int(re.sub(regex,'',str(x[4])))for x in final_list],# remove special characters and convert to integer})print('rows:', boxoffice_df.shape[0])print('columns:', boxoffice_df.shape[1])print('\ndata types:')print(boxoffice_df.dtypes)
boxoffice_df.head(15)Altyapı:
rows:15500columns:5
data types:
lifetime_gross int64
rank int64
studio object
title object
year int64
dtype: object
Altyapı:
lifetime_gross
rank
studio
title
year
0
936662225
1
BV
Star Wars: The Force Awakens
2015
1
760507625
2
Fox
Avatar
2009
2
681084109
3
BV
Black Panther
2018
3
659363944
4
Par.
Titanic
1997
4
652270625
5
Uni.
Jurassic World
2015
5
623357910
6
BV
Marvel's The Avengers
2012
6
620181382
7
BV
Star Wars: The Last Jedi
2017
7
534858444
8
WB
The Dark Knight
2008
8
532177324
9
BV
Rogue One: A Star Wars Story
2016
9
504014165
10
BV
Beauty and the Beast (2017)
2017
10
486295561
11
BV
Finding Dory
2016
11
474544677
12
Fox
Star Wars: Episode I - The Phantom Menace
1999
12
460998007
13
Fox
Star Wars
1977
13
459005868
14
BV
Avengers: Age of Ultron
2015
14
448139099
15
WB
The Dark Knight Rises
2012
'star' kelimesi, ilk on beş filmden beşinde geçtiği için en üst sıralardadır ve Star Wars serisinin, aralarında birkaçı üst sıralarda yer alan daha fazla filmi olduğunu da biliyorsunuz.
Şimdi geliştirdiğiniz kodu kullanalım ve bu veri kümesinde nasıl çalıştığını görelim. Aşağıdaki kodda yeni bir şey yok; sadece hepsini tek bir fonksiyonda topladınız:
defword_frequency(text_list, num_list, sep=None):
word_freq = defaultdict(lambda:[0,0])for text, num inzip(text_list, num_list):for word in text.split(sep=sep):
word_freq[word][0]+=1
word_freq[word][1]+= num
columns ={0:'abs_freq',1:'wtd_freq'}
abs_wtd_df =(pd.DataFrame.from_dict(word_freq, orient='index').rename(columns=columns ).sort_values('wtd_freq', ascending=False).assign(rel_value=lambda df: df['wtd_freq']/ df['abs_freq']).round())
abs_wtd_df.insert(1,'abs_perc', value=abs_wtd_df['abs_freq']/ abs_wtd_df['abs_freq'].sum())
abs_wtd_df.insert(2,'abs_perc_cum', abs_wtd_df['abs_perc'].cumsum())
abs_wtd_df.insert(4,'wtd_freq_perc', abs_wtd_df['wtd_freq']/ abs_wtd_df['wtd_freq'].sum())
abs_wtd_df.insert(5,'wtd_freq_perc_cum', abs_wtd_df['wtd_freq_perc'].cumsum())return abs_wtd_df
word_frequency(boxoffice_df['title'], boxoffice_df['lifetime_gross']).head()Altyapı:
abs_freq
abs_perc
abs_perc_cum
wtd_freq
wtd_freq_perc
wtd_freq_perc_cum
rel_value
The
3055
0.068747
0.068747
67518342498
0.081167
0.081167
22100930.0
the
1310
0.029479
0.098227
32973100860
0.039639
0.120806
25170306.0
of
1399
0.031482
0.129709
30180592467
0.036282
0.157087
21572975.0
and
545
0.012264
0.141973
12188113847
0.014652
0.171739
22363512.0
2
158
0.003556
0.145529
9032673058
0.010859
0.182598
57168817.0
Şaşırtıcı olmayan şekilde, 'stop word'ler en üstte; bu çoğu belge koleksiyonu için benzerdir. Ayrıca bazıları büyük harfle, bazıları küçük harfle yazıldığı için yinelenmiş durumdalar. Dolayısıyla ilgilenmeniz gereken iki açık konu var:
Tüm stop word’leri kaldırın: Bunu fonksiyona yeni bir parametre ekleyip, kendi stop word listenizi sağlayarak yapabilirsiniz.
Tüm kelimeleri küçük harfe çevirerek yinelenmeyi önleyin
İşte fonksiyonun basit bir güncellemesi (yeni rm_words parametresi ve 6, 7, 8. satırlar):
# words will be expandeddefword_frequency(text_list, num_list, sep=None, rm_words=('the','and','a')):
word_freq = defaultdict(lambda:[0,0])for text, num inzip(text_list, num_list):for word in text.split(sep=sep):# This should take care of ignoring the word if it's in the stop wordsif word.lower()in rm_words:continue# .lower() makes sure we are not duplicating words
word_freq[word.lower()][0]+=1
word_freq[word.lower()][1]+= num
columns ={0:'abs_freq',1:'wtd_freq'}
abs_wtd_df =(pd.DataFrame.from_dict(word_freq, orient='index').rename(columns=columns ).sort_values('wtd_freq', ascending=False).assign(rel_value=lambda df: df['wtd_freq']/ df['abs_freq']).round())
abs_wtd_df.insert(1,'abs_perc', value=abs_wtd_df['abs_freq']/ abs_wtd_df['abs_freq'].sum())
abs_wtd_df.insert(2,'abs_perc_cum', abs_wtd_df['abs_perc'].cumsum())
abs_wtd_df.insert(4,'wtd_freq_perc', abs_wtd_df['wtd_freq']/ abs_wtd_df['wtd_freq'].sum())
abs_wtd_df.insert(5,'wtd_freq_perc_cum', abs_wtd_df['wtd_freq_perc'].cumsum())
abs_wtd_df = abs_wtd_df.reset_index().rename(columns={'index':'word'})return abs_wtd_dfAltyapı:
Şimdi ikisini karşılaştırmak ve gizli eğilimleri görmek için görselleştirelim:
import matplotlib.pyplot as plt
plt.figure(figsize=(20,8))
plt.subplot(1,2,1)
word_freq_df_abs = word_freq_df.sort_values('abs_freq', ascending=False).reset_index()
plt.barh(range(20),list(reversed(word_freq_df_abs['abs_freq'][:20])), color='#288FB7')for i, word inenumerate(word_freq_df_abs['word'][:20]):
plt.text(word_freq_df_abs['abs_freq'][i],20-i-1,
s=str(i+1)+'. '+ word +': '+str(word_freq_df_abs['abs_freq'][i]),
ha='right', va='center', fontsize=14, color='white', fontweight='bold')
plt.text(0.4,-1.1, s='Number of times the word was used in a movie title; out of 15500 movies.', fontsize=14)
plt.text(0.4,-1.8, s='Data: boxofficemojo.com Apr. 2018. Feedback: @eliasdabbas', fontsize=14)
plt.vlines(range(0,210,10),-1,20, colors='gray', alpha=0.1)
plt.hlines(range(0,20,2),0,210, colors='gray', alpha=0.1)
plt.yticks([])
plt.xticks([])
plt.title('Words Most Used in Movie Titles', fontsize=22, fontweight='bold')# =============
plt.subplot(1,2,2)# plt.axis('off')
plt.barh(range(20),list(reversed(word_freq_df['wtd_freq'][:20])), color='#288FB7')for i, word inenumerate(word_freq_df['word'][:20]):
plt.text(word_freq_df['wtd_freq'][i],20-i-1,
s=str(i+1)+'. '+ word +': '+'$'+str(round(word_freq_df['wtd_freq'][i]/1000_000_000,2))+'b',
ha='right', va='center', fontsize=14, color='white', fontweight='bold')
plt.text(0.4,-1.1, s='Alltime boxoffice revenue of all movies whos title contained the word. (Top word is "2") ', fontsize=14)
plt.text(0.4,-1.8, s='Data collection & methodology: http://bit.ly/word_freq', fontsize=14)
plt.vlines(range(0,9_500_000_000,500_000_000),-1,20, colors='gray', alpha=0.1)
plt.hlines(range(0,20,2),0,10_000_000_000, colors='gray', alpha=0.1)
plt.xlim((-70_000_000,9_500_000_000))
plt.yticks([])
plt.xticks([])
plt.title('Words Most Associated With Boxoffice Revenue', fontsize=22, fontweight='bold')
plt.tight_layout(pad=0.01)
plt.show()Altyapı:
Görünüşe göre en azından yapımcıların ve yazarların zihninde aşk her şeye galip geliyor! Tüm film adlarında en çok kullanılan kelime o. Ancak ağırlıklandırılmış sıklık (gişe geliri) söz konusu olduğunda o kadar yukarıda değil.
Başka bir deyişle, tüm film başlıklarına bakarsanız, en çok karşınıza çıkacak kelime 'love' olurdu. Ancak izleyicilerin gözünde en çok hangi kelimenin göründüğünü (metrik olarak toplam gişe gelirini kullanarak) tahmin ederseniz, '2', 'star' ve 'man' en çok görüntülenen ya da en fazla gelirle ilişkilendirilenler olurdu.
Açıklık getirmek gerekirse: bunlar çok basit hesaplamalar. 'love' kelimesinin ağırlıklandırılmış sıklığının 1.604.106.767 olduğunu söylediğinizde, bu yalnızca başlığında 'love' kelimesi geçen tüm filmlerin toplam ömür boyu gişe gelirinin bu tutar olduğu anlamına gelir.
'2' kelimesinin en üstte olması da ilginç. Elbette bu bir kelime değil; ancak film serilerinin ikinci bölümlerinin çok büyük bir toplam oluşturduğunu gösteriyor. Beşinci sıradaki '3' için de aynı durum geçerli. 'part' ve 'ii' ifadelerinin de ilk onda olması bu gerçeği doğruluyor.
'American' ve 'movie' yüksek göreli değere sahip.
Bu fonksiyonda kullanılan stop word’lere dair kısa bir not
Genellikle burada olandan daha kapsamlı bir stop word listesi sağlarsınız; özellikle makaleler veya sosyal medya gönderileriyle uğraşıyorsanız. Örneğin nltk paketi çeşitli dillerde stop word listeleri sağlar; bunlar indirilebilir ve kullanılabilir.
Buradaki kelimeler, üst sıralardaki filmler üzerinde birkaç kontrol yapıldıktan sonra seçildi. Bunların birçoğu genellikle stop word kabul edilir; ancak film adları söz konusu olduğunda bazılarını tutmak mantıklıydı; çünkü fikir verebilirler. Örneğin 'I', 'me', 'you' kelimeleri bazı sosyal dinamiklere işaret edebilir. Bir diğer neden de film adlarının çok kısa ifadeler olması ve onlardan mümkün olduğunca anlam çıkarmaya çalışmamızdır.
Kesinlikle kendi kelime listenizle deneyebilir ve biraz farklı sonuçlar görebilirsiniz.
Orijinal film başlıkları listesine geri döndüğümüzde, en üstteki bazı kelimelerin ilk onda bile yer almadığını görüyoruz ve bu, tam da bu yaklaşımla ortaya çıkarmaya çalıştığımız içgörü türüdür.
İlk adım olarak daha fazla kelime elde etmeyi deneyebilirsiniz: film adları son derece kısadır ve çoğu zaman kelimelerin gerçek anlamını yansıtmaz. Örneğin, bir vaftiz babası normalde bir çocuğun vaftizine tanıklık eden ve o çocuğa bakmayı taahhüt eden kişidir (ya da belki keyif için öldüren bir mafya babası?!).
Bir sonraki egzersiz, film adına ek olarak daha ayrıntılı açıklamalar elde etmek olabilir. Örneğin:
"Bir bilgisayar korsanı, gizemli isyancılardan gerçekliğinin gerçek doğasını ve denetleyicilerine karşı savaştaki rolünü öğrenir."
bize 'The Matrix'ten çok daha fazlasını anlatır.
Alternatif olarak, analizinizi zenginleştirmek için aşağıdaki yollardan birini de izleyebilirsiniz:
Daha iyi istatistiksel analiz: aşırı değerlerin/aykırı değerlerin ele alınması, diğer metriklerin kullanılması.
Metin madenciliği: benzer kelimeleri ve konuları bir araya getirme ('happy', 'happiness', 'happily', vb.)
Daha ayrıntılı analiz: aynı fonksiyonu farklı yıllar/on yıllar veya belirli yapım stüdyoları için çalıştırma.
Veriyi kendinizin ve diğer verileri de keşfetmek isteyebilirsiniz:
Hangi kelimenin ağırlıklandırılmış sıklığı en yüksek?
Artık film başlıklarındaki kelime sayımlarını incelediniz, mutlak ve ağırlıklandırılmış sıklık arasındaki farkı ve birini göz ardı etmenin tablonun büyük bir kısmını kaçırmanıza nasıl yol açabileceğini gördünüz. Ayrıca bu yaklaşımın sınırlamalarını gördünüz ve analizinizi nasıl geliştirebileceğinize dair bazı önerileriniz var.
Benzer sayılar içeren herhangi bir metin veri kümesini kolayca analiz etmek için çalıştırabileceğiniz özel bir fonksiyonu oluşturma sürecinden geçtiniz ve bu tür bir veri kümesini anlamanızı nasıl geliştirebileceğini öğrendiniz.
Bunu tweet performansınızı, web sitenizin URL’lerini, Facebook gönderilerinizi veya karşılaşabileceğiniz benzer herhangi bir veri kümesini analiz ederek deneyin.
Kelime sıklığını nasıl oluşturacağınızı öğrenmek için DataCamp’in Python Sözlükleri Eğitimine ve kelime sıklığı dağılımlarını nasıl çizeceğinizi öğrenmek için Python’da Web Kazıma & NLP eğitimine göz atın.
Algoritmalar, sistem tasarımı ve davranışsal senaryoları kapsayan bu temel sorularla teknik mülakat sürecine hakim olun. Uzman cevapları, kod örnekleri ve kanıtlanmış hazırlık stratejileri edinin.
Git deponuzu temiz tutmak için .gitignore’u nasıl kullanacağınızı öğrenin. Bu eğitim; temelleri, yaygın kullanım durumlarını ve başlamanıza yardımcı olacak pratik örnekleri kapsar!
Metin madenciliğinde önemli metrik kümelerinden biri, belirli bir metin dokümanları külliyatındaki kelimelerin (veya herhangi bir token’ın) sıklığıyla ilgilidir. Ancak, her belgenin belgeye ait belirli bir niteliği tanımlayan sayısal bir değerle ilişkilendirildiği durumlarda, ilave metrik kümeleri de kullanabilirsiniz.
Bazı örnekler:
Bu eğitimde,
collectionsmodülünündefaultdictveri yapısından, nihai çıktıyı yönetmek için de pandasDataFramelerinden yararlanacaksınız.Mutlak ve Ağırlıklandırılmış Kelime Sıklığı: Giriş
İki tweet’iniz olduğunu ve içerikleri ile gösterim (görüntüleme) sayılarının aşağıdaki gibi olduğunu varsayalım:
Basit analizi yapmak ve kelimelerinizin 'france' ve 'spain' arasında 50:50 bölündüğünü bulmak kolaydır. Çoğu durumda elinizde yalnızca bu olur ve sadece kelimelerin mutlak sıklığını ölçebilir, bazı ilişkileri çıkarsamaya çalışabilirsiniz. Bu örnekte ise her belgeye dair bazı verileriniz var.
Burada ağırlıklandırılmış sıklık belirgin şekilde farklıdır ve dağılım 80:20’dir. Başka bir deyişle, tweet’lerinizde 'spain' ve 'france' birer kez görünse de, okuyucularınızın gözünde ilki 800, ikincisi 200 kez görünmüştür. Büyük fark!
defaultdictkullanarak Basit Kelime SıklığıŞimdi benzer bir belge kümesi için biraz daha kapsamlı şu örneği ele alalım:
Şimdi belgeler arasında döngü kuruyor, onları kelimelere ayırıyor ve her kelimenin kaç kez geçtiğini sayıyorsunuz:
Yukarıdaki döngüde ilk satır,
text_listüzerinde birer birer gezinir. İkinci satır (her belge için), öğeyi boşluk karakterine göre bölerek (başka bir karakter de olabilirdi ('-', ',', '_', vb.)) kelimeleri arasında döngü yapar.word_freq[word]’a bir değer atamaya çalıştığınızda iki olası senaryo vardır:wordanahtarı vardır: bu durumda atama yapılır (bir eklenir)wordanahtarıword_freqiçinde yoktur; bu durumdadefaultdict, ilk tanımlandığında kendisine atanan varsayılan fonksiyonu çağırır; burada bu fonksiyonint’tir.intçağrıldığında sıfır döndürür. Artık anahtar vardır, değeri sıfırdır ve değerine 1 eklenerek atama yapılmaya hazırdır.İlk tabloda üst sıradaki kelime 'france' iken, her belgedeki tüm kelimeler sayıldıktan sonra 'spain' ve 'beaches'in birincilikte başa baş olduğunu görüyoruz. Bu, özellikle üzerinde çalıştığınız belge listesi onlarca ya da yüz binlerce öğeden oluştuğunda gizli eğilimleri ortaya çıkarmada önemlidir.
Ağırlıklandırılmış Kelime Sıklığı
Artık külliyattaki her kelimenin geçişlerini saydığınıza göre, ağırlıklandırılmış sıklığı görmek istiyorsunuz. Yani, kelimelerin okuyucularınıza kaç kez göründüğünü, sizin onları kaç kez kullandığınıza kıyasla görmek istiyorsunuz.
İlk tabloda kelimelerin mutlak sıklığı 'spain' ve 'france' arasında eşit dağılmıştı, ancak 'spain' bariz biçimde daha fazla ağırlığa sahipti; çünkü değeri 800 iken 'france' için 200’dü.
Peki ikinci, biraz daha karmaşık tablo için ağırlıklandırılmış kelime sıklığı ne olurdu?
Hadi bulalım!
Yukarıda kullandığınız kodun bir kısmını, bazı eklemelerle yeniden kullanabilirsiniz:
Bazı gözlemler:
rel_value, her kelimenin geçiş başına değerini elde etmek için yapılan basit bir bölmedir.rel_value’a bakınca, 'france'wtd_freqmetriğinde oldukça düşük olsa da, geçiş başına değeri yüksek olduğu için potansiyel barındırdığı görülüyor. Bu, örneğin 'france' kapsamındaki içeriklerinizi artırmayı düşündürebilir.Ayrıca, toplamın çoğunluğunu kaç kelimenin oluşturduğuna daha iyi bir perspektiften bakmak için her tür sıklığın yüzdelerini ve kümülatif yüzdelerini gösteren bazı diğer metrikleri de eklemek isteyebilirsiniz:
Daha fazla analiz yapılabilir ve daha fazla veriyle genellikle daha çok sürprizle karşılaşırsınız.
Peki bu, gerçek verilerle gerçek dünyada nasıl görünür?
Film adlarına bakacak, başlıklarda en çok hangi kelimelerin kullanıldığını —yani mutlak sıklığı— ve en çok hangi kelimelerin gelirle ilişkilendirildiğini, yani ağırlıklandırılmış sıklığı göreceksiniz.
Boxoffice Mojo 15.000’den fazla filmi, ilgili gişe geliri ve sıralamalarıyla birlikte listeliyor.
requestsveBeautifulSoupkullanarak veriyi kazıyarak başlayın — İsterseniz Boxoffice Mojo’yu burada şimdiden keşfedebilirsiniz:Bazı sayısal değerlerde özel karakterler (
$,,ve^) yer aldığını ve bazı değerlerin aslındaN/Aolduğunu göreceksiniz. Dolayısıyla bunları dönüştürmeniz gerekir:Şimdi listeyi uygun adlarla sütunlarını adlandırıp, istediğiniz veri türlerine dönüştürerek bir pandas
DataFrame’ine çeviriyorsunuz.'star' kelimesi, ilk on beş filmden beşinde geçtiği için en üst sıralardadır ve Star Wars serisinin, aralarında birkaçı üst sıralarda yer alan daha fazla filmi olduğunu da biliyorsunuz.
Şimdi geliştirdiğiniz kodu kullanalım ve bu veri kümesinde nasıl çalıştığını görelim. Aşağıdaki kodda yeni bir şey yok; sadece hepsini tek bir fonksiyonda topladınız:
Şaşırtıcı olmayan şekilde, 'stop word'ler en üstte; bu çoğu belge koleksiyonu için benzerdir. Ayrıca bazıları büyük harfle, bazıları küçük harfle yazıldığı için yinelenmiş durumdalar. Dolayısıyla ilgilenmeniz gereken iki açık konu var:
İşte fonksiyonun basit bir güncellemesi (yeni
rm_wordsparametresi ve 6, 7, 8. satırlar):Aynı DataFrame’e
abs_freq’e göre sıralanmış olarak bakalım:Şimdi ikisini karşılaştırmak ve gizli eğilimleri görmek için görselleştirelim:
Görünüşe göre en azından yapımcıların ve yazarların zihninde aşk her şeye galip geliyor! Tüm film adlarında en çok kullanılan kelime o. Ancak ağırlıklandırılmış sıklık (gişe geliri) söz konusu olduğunda o kadar yukarıda değil.
Başka bir deyişle, tüm film başlıklarına bakarsanız, en çok karşınıza çıkacak kelime 'love' olurdu. Ancak izleyicilerin gözünde en çok hangi kelimenin göründüğünü (metrik olarak toplam gişe gelirini kullanarak) tahmin ederseniz, '2', 'star' ve 'man' en çok görüntülenen ya da en fazla gelirle ilişkilendirilenler olurdu.
Açıklık getirmek gerekirse: bunlar çok basit hesaplamalar. 'love' kelimesinin ağırlıklandırılmış sıklığının 1.604.106.767 olduğunu söylediğinizde, bu yalnızca başlığında 'love' kelimesi geçen tüm filmlerin toplam ömür boyu gişe gelirinin bu tutar olduğu anlamına gelir.
'2' kelimesinin en üstte olması da ilginç. Elbette bu bir kelime değil; ancak film serilerinin ikinci bölümlerinin çok büyük bir toplam oluşturduğunu gösteriyor. Beşinci sıradaki '3' için de aynı durum geçerli. 'part' ve 'ii' ifadelerinin de ilk onda olması bu gerçeği doğruluyor.
'American' ve 'movie' yüksek göreli değere sahip.
Bu fonksiyonda kullanılan stop word’lere dair kısa bir not
Genellikle burada olandan daha kapsamlı bir stop word listesi sağlarsınız; özellikle makaleler veya sosyal medya gönderileriyle uğraşıyorsanız. Örneğin
nltkpaketi çeşitli dillerde stop word listeleri sağlar; bunlar indirilebilir ve kullanılabilir.Buradaki kelimeler, üst sıralardaki filmler üzerinde birkaç kontrol yapıldıktan sonra seçildi. Bunların birçoğu genellikle stop word kabul edilir; ancak film adları söz konusu olduğunda bazılarını tutmak mantıklıydı; çünkü fikir verebilirler. Örneğin 'I', 'me', 'you' kelimeleri bazı sosyal dinamiklere işaret edebilir. Bir diğer neden de film adlarının çok kısa ifadeler olması ve onlardan mümkün olduğunca anlam çıkarmaya çalışmamızdır.
Kesinlikle kendi kelime listenizle deneyebilir ve biraz farklı sonuçlar görebilirsiniz.
Orijinal film başlıkları listesine geri döndüğümüzde, en üstteki bazı kelimelerin ilk onda bile yer almadığını görüyoruz ve bu, tam da bu yaklaşımla ortaya çıkarmaya çalıştığımız içgörü türüdür.
Sıradaki mantıklı adım, ilginç olan üst kelimeleri daha fazla keşfetmek olabilir. '2' içeren filmleri filtreleyelim ve görelim:
Üst 'star' filmlerine de bir göz atalım:
Ve son olarak, üst 'man' filmleri:
Sonraki Adımlar ve İyileştirmeler
İlk adım olarak daha fazla kelime elde etmeyi deneyebilirsiniz: film adları son derece kısadır ve çoğu zaman kelimelerin gerçek anlamını yansıtmaz. Örneğin, bir vaftiz babası normalde bir çocuğun vaftizine tanıklık eden ve o çocuğa bakmayı taahhüt eden kişidir (ya da belki keyif için öldüren bir mafya babası?!).
Bir sonraki egzersiz, film adına ek olarak daha ayrıntılı açıklamalar elde etmek olabilir. Örneğin:
bize 'The Matrix'ten çok daha fazlasını anlatır.
Alternatif olarak, analizinizi zenginleştirmek için aşağıdaki yollardan birini de izleyebilirsiniz:
Veriyi kendinizin ve diğer verileri de keşfetmek isteyebilirsiniz:
Artık film başlıklarındaki kelime sayımlarını incelediniz, mutlak ve ağırlıklandırılmış sıklık arasındaki farkı ve birini göz ardı etmenin tablonun büyük bir kısmını kaçırmanıza nasıl yol açabileceğini gördünüz. Ayrıca bu yaklaşımın sınırlamalarını gördünüz ve analizinizi nasıl geliştirebileceğinize dair bazı önerileriniz var.
Benzer sayılar içeren herhangi bir metin veri kümesini kolayca analiz etmek için çalıştırabileceğiniz özel bir fonksiyonu oluşturma sürecinden geçtiniz ve bu tür bir veri kümesini anlamanızı nasıl geliştirebileceğini öğrendiniz.
Bunu tweet performansınızı, web sitenizin URL’lerini, Facebook gönderilerinizi veya karşılaşabileceğiniz benzer herhangi bir veri kümesini analiz ederek deneyin.
Kodu depo olarak klonlamak ve kendiniz denemek daha kolay olabilir.
word_frequencyfonksiyonu, indirilip çalışmalarınızda/araştırmalarınızda kullanmayı deneyebileceğiniz advertools paketinin bir parçasıdır.Göz atın ve bana bildirin! @eliasdabbas
Kelime sıklığını nasıl oluşturacağınızı öğrenmek için DataCamp’in Python Sözlükleri Eğitimine ve kelime sıklığı dağılımlarını nasıl çizeceğinizi öğrenmek için Python’da Web Kazıma & NLP eğitimine göz atın.