Bu, efsanevi sanatçı Prince’in şarkı sözleri üzerine bir vaka çalışmasında R kullanarak çeşitli analitik görevler yapacağınız, üç bölümlük bir eğitim serisinin Birinci Bölümü. Üç eğitim şu konuları kapsar:
Birinci Bölüm: Metin Madenciliği ve Keşifsel Analiz
Müzik sözleri bir sanatçının bakış açısını yansıtabilir, ancak popüler şarkılar toplumun duymak istediklerini ortaya koyar. Şarkı sözü analizi kolay bir iş değildir. Düz yazıdan çok farklı yapılandığı için varsayımlarda dikkatli olmayı ve özgün bir analitik teknik seçimini gerektirir. Şarkı sözleri hayatımıza sızar ve düşüncelerimizi fark edilmeden etkiler. Öngörücü Şarkı Sözleri kavramı yeni yeni konuşulmaya başlandı ve araştırma makaleleri ile lisansüstü tezlerde giderek daha çok yer buluyor. Bu vaka çalışması, bu gelişmekte olan konunun yalnızca birkaç yönüne değinecek.
Prince: Sanatçı
Prince’in geride bıraktığı ilham verici ve çeşitli eserlerini kutlamak için, sözlerinde bazen açık, çoğu zaman gizli mesajları keşfedeceksiniz. Yine de, dünya çapında pek çok türün gelişimindeki etkisini takdir etmek için Prince’in müziğini sevmeniz gerekmez. Rolling Stone dergisi, Prince’i tüm zamanların en iyi 18. söz yazarı olarak, Bob Dylan, John Lennon, Paul Simon, Joni Mitchell ve Stevie Wonder gibi isimlerin hemen arkasında listeler. Şarkı sözü analizi, "Hit Şarkıları" öngörme olasılığı gerçeğe yaklaşırken yavaş yavaş veri bilimi topluluklarında yer buluyor.
Prince müzikle taşan bir adamdı — çılgınca üretken bir söz yazarı, gitarlar, klavyeler ve davullarda virtüöz ve müziği türleri aşıyor olsa da funk, rock, R&B ve pop’un usta bir mimarı. - Jon Pareles (NY Times)
Bu eğitimin, serinin Birinci Bölümü olan kısmında, tidy text çerçevesini kullanarak bir dizi şarkı sözü üzerinde metin madenciliği tekniklerinden yararlanacaksınız. Tidy veri setlerinin belirli bir yapısı vardır: her değişken bir sütun, her gözlem bir satır ve her gözlemsel birim türü bir tablodur. Veri setini temizleyip koşullandırdıktan sonra, Prince’in şarkı sözlerinin farklı yönlerine bakarken betimsel istatistikler ve keşifsel görselleştirmeler oluşturacaksınız.
Önkoşullar
Bu eğitim serisinin Birinci Bölümü, tidy veriye ilişkin temel bir anlayış gerektirir — özellikle veri dönüşümü için dplyr, görselleştirmeler için ggplot2 ve kökeni magrittr paketine dayanan %>% pipe operatörü gibi paketler. Her eğitim, analizinizde kullanabileceğiniz araçları tanıtacak, ancak her adımı ayrıntılandırmayabilir. Birçok adımın genellikle %>% operatörüyle birleştirildiğini fark edeceksiniz. Bu aynı zamanda bir vaka çalışması olduğundan, yaptığınız tüm çıkarımların tamamen gözlemsel olduğunu unutmamak önemlidir; dolayısıyla, korelasyon nedenselliği ima etmez.
İpucu: kullanılan araçlar hakkında arka plan için iki iyi kaynak: Garrett Grolemund ve Hadley Wickham’ın R for Data Science’ı; ve Julia Silge ile David Robinson’ın Text Mining with R’ı.
İkinci ve Üçüncü Bölümler
Ayrı bir eğitim olan İkinci Bölüm’de, Prince’in müziğindeki genel ruh halini ve temaları ve bunların toplumsal bakış açılarına uygulanışını yakalamak için Duygu Analizi ve Konu Modellemesini ele alacaksınız. Bir duygu sözlüğü ile çalışacak, ikili ve kategorik duyguları değerlendirecek, zaman içindeki eğilimleri çizecek ve n-gram’lar ile sözcük birlikteliklerine bakacaksınız. Ayrıca Doğal Dil İşleme (NLP) ve Gizli Dirichlet Ayrımı (LDA) ile K-Ortalamalar gibi kümeleme tekniklerini kullanarak sözlerdeki motifleri ortaya çıkaracaksınız.
Bir diğer eğitim olan Üçüncü Bölüm’de ise, keşifsel sonuçlarınızı kullanarak bir şarkının hangi on yılda yayımlandığını ve daha da ilginci, yalnızca sözlerine bakarak Billboard listelerine girip girmeyeceğini tahmin etmeye çalışarak işi tamamlayacaksınız. Karar Ağaçları (rpart ve C50), En Yakın K-Komşular (class) ve Naive Bayes (e1071) gibi makine öğrenimi araçlarını kullanarak metin kabul edebilen bir sınıflandırıcı üreteceksiniz.
Üç bölümün tamamı, Prince’in şarkı sözleri, yayımlanma yılı ve Billboard liste konumlarından oluşan aynı veri setini kullanacaktır. Bu çalışmadaki teknikler, pek çok başka metin türüne de uygulanabilir. Aslında, standart düzyazı için sonuçlar genellikle daha kolay yorumlanır çünkü şarkı sözleri genel olarak dolaylı mesajlar ve ince nüanslarla tasarlanır.
Özetle, şarkı sözlerini analiz etmek için birçok farklı yöntem vardır. Bu eğitimler, aşağıdaki görselde kırmızıyla vurgulananları kapsar. Bu görselin çok "bulanık" bir resmin yalnızca üst düzey bir temsil olduğunu unutmayın. Ve hayır, kastettiğim görselin kendisi değil! Gerçek şu ki, modelleme ve makine öğrenimi tekniklerinin farklı yönleri artık bulanıklaşmış durumda ve aşağıda gösterildiği gibi tek bir kutuya sığmayabiliyor. Bu yüzden görsele bakarken 3D gözlükleri takın; belki daha anlamlı gelir!
Yeni beceriler öğrenip pratiğini yapmanın yanı sıra, bu eğitim şarkı sözü analizi kavramıyla ilgili temel soruları ele almayı amaçlar. Son çalışmalar, popüler müzikte "sözel zekânın" düşüşte olabileceğini gösteriyor. Bazı çalışmalar, 1 Numaralı Hit Şarkılarda kullanılan kelimelerin ABD’de 3. sınıf öğrencilerinin okuma seviyeleriyle örtüştüğünü dahi öne sürüyor. Böyle bir konuya ışık tutmak için metin madenciliği, NLP, makine öğrenimi ve diğer veri bilimi yöntemlerinden yararlanmak mümkün mü? Bir şarkının nasıl karşılandığına bağlı olarak topluma hitap eden temaları belirlemek mümkün mü? Sadece söz analizine dayanarak bir şarkının başarılı olup olmayacağını tahmin etmek mümkün mü? Bu ilk eğitimde, Prince’in müziğinin sözel karmaşıklığını keşif amaçlı inceleyeceksiniz.
Sorular
Dalmadan önce, neyi keşfetmeye çalıştığınızı düşünün. Hangi sorular ilginizi çekiyor? Önce veri setinin bir analizini adım adım yapacaksınız. Nasıl görünüyor? Kaç şarkı var? Sözler nasıl yapılandırılmış? Ne kadar temizlik ve düzenleme gerekiyor? Gerçekler neler? Kelime sıklıkları nedir ve bu neden önemli? Teknik açıdan, veriyi duygu analizi, NLP ve makine öğrenimi modelleri için anlamak ve hazırlamak istersiniz.
Müzik uzun zamandır kitlelere iletişim kurmanın etkili bir yolu oldu ve şarkı sözleri bu iletişimi iletmede büyük bir rol oynadı. Yine de [toplumun] esenliğinde sözlerin rolüne dair araştırma fırsatı büyük ölçüde yeterince kullanılmıyor. - Patricia Fox Ransom
Veri
Metin madenciliği için veri elde etmenin popüler bir yöntemi, rvest paketini kullanarak web’den içerik kazımaktır. Billboard Liste bilgilerini ve Prince’in şarkı sözlerini çeşitli sitelerden kazıyıp şarkı başlıklarında birleştirebildim. Başlıklar için tutarsız adlandırma kuralları olduğundan biraz düzenleme gerekti. Ardından, orijinal sürüm olmayan, yani remiksler, uzatılmış sürümler, kulüp miksleri, yeniden yapımlar vb. tüm şarkıları kaldırma yönünde öznel bir karar verdim. Ayrıca tekrarları önlemek için Hit Şarkılarının tarihsel derlemelerini içeren albümleri de çıkardım. Biraz küçük temizlik yapıp sonucu bu eğitimde kullanılabilecek bir csv dosyasına kaydettim.
Birinci Bölüm metin madenciliğine odaklandığından, bu eğitim için o kodu dahil etmedim; ancak veri setini indirmek isterseniz buradan erişebilirsiniz.
Kütüphaneleri yükleyin
#most of the libraries needed
library(dplyr) #data manipulation
library(ggplot2) #visualizations
library(gridExtra) #viewing multiple plots together
library(tidytext) #text mining
library(wordcloud2) #creative visualizations
Veriyi içe alın
Bir csv dosyasından veri okumak için birkaç yöntem vardır, ancak ben sözleri, yayımlanma yılını ve Billboard liste konumlarını içeren bir veri çerçevesi yüklemek için read.csv() kullanmayı seçtim. Varsayılan olarak R’nin tüm karakter dizilerini faktöre dönüştürdüğüne dikkat edin. Bu, sonraki adımlarda sorun yaratabilir; fakat stringsAsFactors parametresini FALSE yaparak bunu önleyebilirsiniz. Şimdi veriyi inceleyelim…
Bu dosyayı ben oluşturduğum için X’in yalnızca bir satır numarası, text’in ise gerçek şarkı sözleri olduğunu biliyorum. Diğer gerekli alanlar arasında şarkı (song), yıl (year) ve Billboard listelerindeki yerini gösteren peak bulunur. US.Pop ve US.R.B, ABD (Pop ve R&B listeleri) için zirve liste konumlarıdır; bunları da koruyun ve şimdilik diğer tüm alanları bırakın.
Bunu, orijinal veri seti olan prince_orig’i alıp %>% ile select()’e aktararak yapın. Böylece kodu soldan sağa okuyabilirsiniz.
Ayrıca, select()’in sütunları tek adımda yeniden adlandırmanıza izin verdiğine dikkat edin. Dolayısıyla text’i lyrics olarak ayarlayın ve US sütunlarını "." yerine "_" kullanarak tidyverse tarzında yeniden adlandırın. Ardından sonucu, eğitim boyunca kullanacağınız prince içinde saklayın. dplyr, verinize transpoze bir görünümde bakmayı kolaylaştıran glimpse() adlı bir işlev sağlar.
prince <- prince_orig %>%
select(lyrics = text, song, year, album, peak,
us_pop = US.Pop, us_rnb = US.R.B)
glimpse(prince[139,])
Observations: 1
Variables: 7
$ lyrics <chr> "I just can't believe all the things people say, controversy\nAm I ...
$ song <chr> "controversy"
$ year <int> 1981
$ album <chr> "Controversy"
$ peak <int> 3
$ us_pop <chr> "70"
$ us_rnb <chr> "3"
İlk açık soru: kaç gözlem ve kaç sütun var?
dim(prince)
[1] 824 7
dim() işlevini kullanarak 7 sütun ve 824 gözlem olduğunu görürsünüz. Her gözlem bir şarkıdır. Dediğim gibi… üretken!
Şarkılardan birinin lyrics sütununa baktığınızda, yapının nasıl olduğunu görebilirsiniz.
str(prince[139, ]$lyrics, nchar.max = 300)
chr "I just can't believe all the things people say, controversy\nAm I Black or White? Am I straight or gay? Controversy\nDo I believe in God? Do I believe in me? Controversy\nControversy, controversy\nI can't understand human curiosity, controversy\nWas it good for you? Was I what you w"| __truncated__
Temizlemek için bolca fırsat var, hadi başlayalım.
Veri Koşullandırma
Temel temizlik
Veriyi koşullandırmak için kullanabileceğiniz farklı yöntemler vardır. Bir seçenek, veri çerçevesini tm metin madenciliği paketiyle bir Korpus ve Belge Terim Matrisi’ne dönüştürmek ve ardından temizlik için tm_map() işlevini kullanmaktır; ancak bu eğitim şimdilik temel konularla sınırlı kalacak ve kirli işleri yapmak için gsub() ve apply() işlevlerini kullanacaktır.
Önce, gsub() kullanarak çoğu senaryoyu ele alan küçük bir işlev oluşturarak o can sıkıcı kısaltmalardan kurtulun ve ardından bu işlevi tüm şarkı sözlerine uygulayın.
# function to expand contractions in an English-language source
fix.contractions <- function(doc) {
# "won't" is a special case as it does not expand to "wo not"
doc <- gsub("won't", "will not", doc)
doc <- gsub("can't", "can not", doc)
doc <- gsub("n't", " not", doc)
doc <- gsub("'ll", " will", doc)
doc <- gsub("'re", " are", doc)
doc <- gsub("'ve", " have", doc)
doc <- gsub("'m", " am", doc)
doc <- gsub("'d", " would", doc)
# 's could be 'is' or could be possessive: it has no expansion
doc <- gsub("'s", "", doc)
return(doc)
}
# fix (expand) contractions
prince$lyrics <- sapply(prince$lyrics, fix.contractions)
Metni bulanıklaştıran özel karakterleri de fark edeceksiniz. Bunları gsub() işlevi ve basit bir düzenli ifadeyle kaldırabilirsiniz. Dikkat: Bu adımdan önce kısaltmaları genişletmek kritik önemdedir!
# function to remove special characters
removeSpecialChars <- function(x) gsub("[^a-zA-Z0-9 ]", " ", x)
# remove special characters
prince$lyrics <- sapply(prince$lyrics, removeSpecialChars)
Tutarlılık için, kullanışlı tolower() işleviyle her şeyi küçük harfe dönüştürün.
# convert everything to lower case
prince$lyrics <- sapply(prince$lyrics, tolower)
Şimdi sözleri incelediğinizde, orijinal ham metnin daha temiz bir sürümünü görürsünüz.
str(prince[139, ]$lyrics, nchar.max = 300)
chr "i just can not believe all the things people say controversy am i black or white
Metin madenciliği için veriyi koşullandırmadaki bir diğer yaygın adım, kelimeleri kök anlamlarına indirgeme ya da gövdeleme (stemming) olarak adlandırılır. Bu başlı başına bir konu olup daha sonra ele alınabilir. Şimdilik, prince veri çerçevesinin özetine bakın.
#get facts about the full dataset
summary(prince)
lyrics song year album
Length:824 Length:824 Min. :1978 Length:824
Class :character Class :character 1st Qu.:1989 Class :character
Mode :character Mode :character Median :1996 Mode :character
Mean :1995
3rd Qu.:1999
Max. :2015
NA's :495
peak us_pop us_rnb
Min. : 0.00 Length:824 Length:824
1st Qu.: 2.00 Class :character Class :character
Median : 7.00 Mode :character Mode :character
Mean :15.48
3rd Qu.:19.00
Max. :88.00
NA's :751
Gördüğünüz gibi, 37 yıllık şarkı var ve (veri setinde bulunan) en düşük listeye giren şarkı 88. sırada. Ayrıca yıl ve peak için oldukça fazla NA olduğunu da görebilirsiniz. Farklı türde analizler yapacağınız için, tam veri setini prince veri çerçevesinde tutun ve gerektiğinde filtreleyin.
Birkaç alan ekleyin
Hedef sorularınızdan biri zaman içinde şarkı eğilimlerine bakmak olduğundan ve veri setinde tek tek yayımlanma yılları bulunduğundan, yılları on yıllık dilimlere (bucket) ayırabilirsiniz. dplyr’ın mutate() fiilini kullanarak yeni decade alanını oluşturun. Dilimleri oluşturmanın bir yolu, ifelse() ile %in% operatörünü birlikte kullanarak yıllara göre filtreleme ve şarkıları on yıllara göre gruplamaktır. Sonra sonuçları tekrar prince içine yazın (özünde yeni bir alan eklemiş olursunuz).
Aynısını, bir şarkının Top 10, Top 100’e ulaşıp ulaşmadığını ya da listeye hiç girmediğini (uncharted) ifade eden chart_level için de yapabilirsiniz. Bunlar birbirini dışlar; dolayısıyla Top 100, Top 10 şarkıları içermez.
#create the chart level column
prince <- prince %>%
mutate(chart_level =
ifelse(prince$peak %in% 1:10, "Top 10",
ifelse(prince$peak %in% 11:100, "Top 100", "Uncharted")))
Ayrıca, bir şarkının Billboard listelerine girip girmediğini gösteren charted adlı ikili bir alan oluşturun (yani popüler bir şarkı). Sonraki eğitimlerde kullanmak üzere write.csv() ile kaydedin.
#create binary field called charted showing if a song hit the charts at all
prince <- prince %>%
mutate(charted =
ifelse(prince$peak %in% 1:100, "Charted", "Uncharted"))
#save the new dataset to .csv for use in later tutorials
write.csv(prince, file = "prince_new.csv")
Betimsel İstatistikler
Grafikleri özelleştirmek için, görsellerin tutarlı kalması adına benzersiz bir renk listesi oluşturmayı seviyorum. Aşağıdaki gibi onaltılık kod temsilleriyle ayırt edilebilir renkler bulabileceğiniz birçok web kaynağı var. Grafikleriniz için bir tercihiniz varsa, gerektiğinde ggplot()’a uygulayabileceğiniz kendi temanızı da oluşturabilirsiniz.
#define some colors to use throughout
my_colors <- c("#E69F00", "#56B4E9", "#009E73", "#CC79A7", "#D55E00")
theme_lyrics <- function()
{
theme(plot.title = element_text(hjust = 0.5),
axis.text.x = element_blank(),
axis.ticks = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.position = "none")
}
Metin madenciliğine girmeden önce, verinizin şarkı düzeyinde neler barındırdığına dair temel bir görünümle başlayın. Prince’in on yıllara göre kaç şarkı yayımladığını görselleştirmek için iyi bir zaman. Hatırlatma: profesyonel kariyeri 1978’de başladı ve 2015’e kadar sürdü (yukarıdaki summary() istatistiklerinde gösterildiği gibi). Ancak şimdi eğilimlere baktığımız ve veri setinde yıl için çok sayıda boş değer olduğu için, ilk grafikte yayımlanma yılı NA olanların tümünü filtrelemek isteyeceksiniz.
Şarkı İstatistikleri
dplyr’ın filter(), group_by() ve summarise() işlevlerini kullanarak on yıla göre gruplama yapabilir ve ardından şarkı sayısını sayabilirsiniz. n() işlevi, gruplandırılmış verilerde summarise() ile kullanımı yararlı birkaç toplulaştırma işlevinden biridir. Sonra ggplot() ve geom_bar() kullanarak bir çubuk grafik oluşturun ve çubukları charted kategorisine göre doldurun.
prince %>%
filter(decade != "NA") %>%
group_by(decade, charted) %>%
summarise(number_of_songs = n()) %>%
ggplot() +
geom_bar(aes(x = decade, y = number_of_songs,
fill = charted), stat = "identity") +
theme(plot.title = element_text(hjust = 0.5),
legend.title = element_blank(),
panel.grid.minor = element_blank()) +
ggtitle("Yayımlanan Şarkılar") +
labs(x = NULL, y = "Şarkı Sayısı")
Bu, en üretken on yılının 1990’lar olduğunu açıkça gösteriyor.
Şimdi chart_level ile benzer bir grafik oluşturun.
Eğilimi görebilmek için hem decade hem chart_level ile group_by() yapmayı unutmayın.
Bu grafikte yalnızca listeye giren şarkılara bakacağınız için peak > 0 kullanarak diğer her şeyi filtreleyin. group_by nesnesini n() ile şarkı sayısını saymak üzere summarise()’a aktarın. Bunu bir değişkende saklarken, basit bir çubuk grafik için ggplot()’a da aktarabilirsiniz.
charted_songs_over_time <- prince %>%
filter(peak > 0) %>%
group_by(decade, chart_level) %>%
summarise(number_of_songs = n())
charted_songs_over_time %>%
ggplot() +
geom_bar(aes(x = decade, y = number_of_songs,
fill = chart_level), stat = "identity") +
theme(plot.title = element_text(hjust = 0.5),
legend.title = element_blank(),
panel.grid.minor = element_blank()) +
labs(x = NULL, y = "Şarkı Sayısı") +
ggtitle("Listeye Giren Şarkılar")
İçgörüler
Prince’in listeye giren tüm şarkıları içinde çoğunluğun Top 10’a ulaştığına dikkat edin. Ama daha da ilginci, yeni şarkılar açısından en üretken on yılı 1990’lar olmasına rağmen, daha çok liste başarısı 1980’lerde yaşanmış. Neden? Metin madenciliği bölümlerini incelerken bu soruyu aklınızda tutun.
Şarkı sözü analizi için tam veri setinin gücünden yararlanmak üzere, liste seviyesi ve yayımlanma yılına dair referansları kaldırarak madencilik yapabileceğiniz çok daha büyük bir şarkı kümesine sahip olabilirsiniz. Bir bakın:
#look at the full data set at your disposal
prince %>%
group_by(decade, chart_level) %>%
summarise(number_of_songs = n()) %>%
ggplot() +
geom_bar(aes(x = decade, y = number_of_songs,
fill = chart_level), stat = "identity") +
theme(plot.title = element_text(hjust = 0.5),
legend.title = element_blank(),
panel.grid.minor = element_blank()) +
labs(x = NULL, y = "Şarkı Sayısı") +
ggtitle("Verideki Tüm Şarkılar")
Gördüğünüz gibi, veride yayımlanma tarihi olmayan yüzlerce Prince şarkısı var. Duygu analizi veya keşifsel analiz için tüm veriyi kullanabilirsiniz; ancak zaman içindeki eğilimler için çalışabileceğiniz çok daha küçük bir küme kalır. Bu sorun değil — yalnızca akılda tutulması gereken bir nokta.
1 Numaralı Şarkılar!
Sıkı Prince hayranları için, listelerde 1 Numara olan şarkılara hızlı bir bakış aşağıda. (knitr ve kableExtra paketlerinden kable() ve kable_styling() ile formattable’dan color_tile() kullanarak güzel biçimlendirilmiş HTML çıktı oluşturabileceğinizi unutmayın.)
library(knitr) # for dynamic reporting
library(kableExtra) # create a nicely formated HTML table
library(formattable) # for the color_tile function
prince %>%
filter(peak == "1") %>%
select(year, song, peak) %>%
arrange(year) %>%
mutate(year = color_tile("lightblue", "lightgreen")(year)) %>%
mutate(peak = color_tile("lightgreen", "lightgreen")(peak)) %>%
kable("html", escape = FALSE, align = "c", caption = "Prince's No. 1 Songs") %>%
kable_styling(bootstrap_options =
c("striped", "condensed", "bordered"),
full_width = FALSE)
Prince's No. 1 Songs
year
song
peak
1979
i wanna be your lover
1
1984
erotic city
1
1984
purple rain
1
1984
when doves cry
1
1985
around the world in a day
1
1986
kiss
1
1988
lovesexy
1
1989
batdance
1
1990
thieves in the temple
1
1991
diamonds and pearls
1
1995
the most beautiful girl in the world
1
2006
3121
1
2007
planet earth
1
Metin Madenciliği
Metin madenciliği, metin analitiği olarak da düşünülebilir. Amaç, muhtemelen bilinmeyen ya da bariz olanın altında gömülü kalmış ilgili bilgileri keşfetmektir. Doğal Dil İşleme (NLP), metin madenciliğinde kullanılan yöntemlerden biridir. Yazılı dildeki belirsizlikleri çözmek için tokenizasyon, kümeleme, varlık ve kelime ilişkilerini çıkarma ve temaları belirlemek ile öznel bilgileri nicelleştirmek için algoritmalar kullanır. Sözel karmaşıklık kavramını parçalayarak başlayacaksınız.
Sözel karmaşıklık farklı bağlamlarda farklı şeyler ifade edebilir; ancak şimdilik, şu ölçülerin birleşimiyle tanımlanabileceğini varsayalım:
Kelime Sıklığı: şarkı başına kelime sayısı
Kelime Uzunluğu: bir metindeki bireysel kelimelerin ortalama uzunluğu
Sözel Çeşitlilik: bir metinde kullanılan benzersiz kelimelerin sayısı (şarkı söz varlığı)
Sözel Yoğunluk: benzersiz kelime sayısının toplam kelime sayısına oranı (kelime tekrarı)
Tidy Metin Biçimi
Analize başlamak için, şarkı sözlerini tek tek kelimelere ayırmanız ve içgörü madenciliğine başlamanız gerekir. Bu işleme tokenizasyon denir.
Veri Biçimleri ve Tokenizasyon
Metin madenciliğinde kullanılabilecek farklı yöntemler ve veri biçimleri olduğunu unutmayın:
Korpus: tm metin madenciliği paketi tarafından oluşturulan belge koleksiyonları
Belge-terim matrisi: korpustaki tüm kelime oluşumlarını belge bazında listeleyen, belgelerin satırlar, kelimelerin sütunlar olduğu matris
Tidy Metin: satır başına bir token içeren bir tablo. Bu vaka çalışmasında bir token bir kelime (veya İkinci Bölüm’de ele alınacak bir n-gram) olacaktır. Tokenizasyon, bu nedenle şarkı sözlerini token’lara bölme işlemidir. Bu eğitimde tidytext’in unnest_tokens() işlevi kullanılacaktır. Daha fazla ayrıntı için tidytext belgelendirmesine bakın.
Ancak herhangi bir tokenizasyondan önce, veriyi temizlemede bir adım daha var. Birçok şarkı sözü, yazıya dökülürken "Repeat Chorus" gibi ifadeler veya "Bridge" ve "Verse" gibi etiketler içerir. Sonuçları bulanıklaştırabilecek başka istenmeyen kelimeler de çoktur. Ön analiz yaptıktan sonra, aradan çıkarmak istediğim birkaçını seçtim.
Aşağıda, elle kaldırılması gereken gereksiz kelimelerin bir listesi bulunuyor:
undesirable_words <- c("prince", "chorus", "repeat", "lyrics",
"theres", "bridge", "fe0f", "yeah", "baby",
"alright", "wanna", "gonna", "chorus", "verse",
"whoa", "gotta", "make", "miscellaneous", "2",
"4", "ooh", "uurh", "pheromone", "poompoom", "3121",
"matic", " ai ", " ca ", " la ", "hey", " na ",
" da ", " uh ", " tin ", " ll", "transcription",
"repeats")
Token’ları açmak için, zaten yüklenmiş olan tidytext kütüphanesini kullanın. Artık dplyr’ın yeteneklerinden yararlanabilir ve birkaç adımı birleştirebilirsiniz.
Tidy metin çerçevesinden, hem metni tekil token’lara (tokenizasyon) bölmeniz hem de tidy bir veri yapısına dönüştürmeniz gerekir. Bunu yapmak için tidytext’in unnest_tokens() işlevini kullanın. unnest_tokens(), en az iki argüman gerektirir: metin çözülürken oluşturulacak çıktı sütununun adı (bu durumda "word") ve mevcut metni tutan girdi sütunu (ör. lyrics).
prince veri setini alıp unnest_tokens()’a aktarabilir ve ardından durdurma (stop) kelimelerini kaldırabilirsiniz. Stop kelimeler nelerdir? Çok iyi bildiğiniz, sonuçlarımıza anlam katmayabilecek kadar yaygın kelimelerdir. Seçilebilecek farklı listeler vardır; burada tidytext paketindeki stop_words sözlüğünü kullanacaksınız.
Bu stop kelimelerden rastgele bir liste göstermek için sample(), 15 kelimeyle sınırlamak için head() kullanın.
Dolayısıyla, şarkı sözlerini kelimelere ayırdıktan sonra, dplyr’ın anti_join() işlevini kullanarak stop kelimeleri kaldırabilirsiniz. Ardından, önceden tanımlanan istenmeyen kelimelerden dplyr’ın filter() fiili ve %in% operatörü ile kurtulun. Sonra yinelenen kayıtları kaldırmak için distinct() kullanın. Son olarak, dört karakterden kısa tüm kelimeleri kaldırabilirsiniz. Bu da öznel bir karardır; ancak sözlerde bunlar çoğunlukla "yea ve hey" gibi ünlemlerdir. Sonuçları prince_words_filtered içine kaydedin.
Not: gelecekte başvurmak üzere, prince_words_filtered; 1) stop kelimeler, 2) istenmeyen kelimeler ve 3) 1-3 karakterli kelimeler olmadan prince veri çerçevesinin tidy metin sürümüdür. Bunu bazı analizlerde kullanacak, bazılarında kullanmayacaksınız.
#unnest and remove stop, undesirable and short words
prince_words_filtered <- prince %>%
unnest_tokens(word, lyrics) %>%
anti_join(stop_words) %>%
distinct() %>%
filter(!word %in% undesirable_words) %>%
filter(nchar(word) > 3)
stop_words’un bir word sütunu olduğunu ve unnest_tokens() tarafından word adlı yeni bir sütun oluşturulduğunu fark edin; dolayısıyla anti_join() otomatik olarak word sütununda birleştirir.
Artık yeni tidy veri yapınızın sınıfını ve boyutlarını inceleyebilirsiniz:
class(prince_words_filtered)
[1] "data.frame"
dim(prince_words_filtered)
[1] 36916 10
prince_words_filtered, toplam 36916 kelime (benzersiz olmayan) ve 10 sütundan oluşan bir veri çerçevesidir. İşte bir anlık görüntü: (Sadece bir kelime seçip 10 şarkıdaki görünümlerini sınırladım ve ilgi çekici alanları sırayla yazdırmak için select() kullandım; yine biçimlendirme için knitr kullandım). Bu size token’lanmış, özetlenmemiş, tidy veri yapısını gösterir.
Her satırın, göründüğü her şarkı için yinelenecek tek bir kelime içerdiğini görebilirsiniz.
Kelime Sıklığı
Müzikte, tek tek kelime sıklıkları ister tekrar ister nadirlik olsun büyük önem taşır. Her ikisi de şarkının akılda kalıcılığını etkiler. Bir söz yazarı bilmek isteyebilir: kelime sıklığı ile hit şarkılar arasında bir ilişki var mı? Şimdi, tidy biçimi bir adım daha ileri götürüp şarkı başına kelime sayısının özetlenmiş dökümünü elde etmek istiyorsunuz.
Prince’in sözlerinde bu biçimi incelemek için, Billboard Listelerindeki konuma göre şarkı bazında gruplanmış kelime sayımı dağılımını gösteren bir histogram oluşturun. Gerçek bir kelime sıklığı sayımı elde etmek için prince sözlerini, hiçbir kelimeyi filtrelemeden tekrar unnest edin. Yine group_by() ve summarise() kullanarak sayımları alın. Ardından, dplyr’ın arrange() fiilini kullanarak sayıya göre sıralayın. Önce en yüksek sayılara bakın, sonra histogram için ggplot() kullanın.
Sağa çarpık olduğuna dikkat edin. Şarkı sözü dökümünün doğası gereği, veri girişi hatalarından şüpheliyim. O yüzden, meraktan, 800’ün üzerinde kelimeye sahip o Top 10 şarkıya bir göz atın.
Biraz araştırma yaptım ve bu şarkıda rap bölümü icra eden bir konuk sanatçı olduğunu keşfettim. Bu da durumu açıklıyor! Bu veri setinin dünya genelinde Pop ve R&B listelerini kapsadığını unutmayın; dolayısıyla tür ve coğrafya varsayımlarınızı büyük ölçüde etkileyebilir. Örneğin, Kanada’da 5’e kadar yükselmesine karşın, ABD Pop listesi sıralamasının çok daha düşük olduğuna dikkat edin. Aklınızda bulunsun.
Öneri: Müzik analizini kendi başınıza ele almak isterseniz, neredeyse 50.000 sanatçı için 50’den fazla özelliğe (ör. tempo, ses yüksekliği, dans edilebilirlik vb.) sahip The Million Song Dataset’e göz atabilirsiniz! Şarkı sözlerine müzikal özellikler eklemek oldukça kapsamlı bir analiz sağlar.
En Sık Kelimeler
Tam söz kümesinde en sık kullanılan kelimeleri basitçe değerlendirmek için, temizlenmiş ve filtrelenmiş veri setinizde count() ve top_n() kullanarak en üst n kelimeyi alabilirsiniz. Ardından, kelimeleri sayıya göre sıralamak için reorder() kullanın ve dplyr’ın mutate() fiiliyle sıralanmış değeri word’a yeniden atayın. Bu, ggplot()’un güzelce göstermesini sağlar.
prince_words_filtered %>%
count(word, sort = TRUE) %>%
top_n(10) %>%
ungroup() %>%
mutate(word = reorder(word, n)) %>%
ggplot() +
geom_col(aes(word, n), fill = my_colors[4]) +
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5),
panel.grid.major = element_blank()) +
xlab("") +
ylab("Şarkı Sayısı") +
ggtitle("Prince Şarkı Sözlerinde En Sık Kullanılan Kelimeler") +
coord_flip()
Çoğu popüler müzikte olduğu gibi, love (aşk) yaygın bir tema gibi görünüyor. Sadece bu en üst kelimelere bakarak pek fazla varsayımda bulunmazdım; ancak sanatçının bakış açısına dair kesinlikle bazı içgörüler elde edebilirsiniz, yalnız tüm resmi vermez. Daha derine inmeden önce kısa bir görsel eğlence molası verin.
Kelime Bulutları
Kelime bulutları birçok çevrede kötü bir üne sahiptir ve dikkatli olmazsanız uygun olmayan bağlamlarda kullanılabilirler. Ancak doğası gereği hepimiz çok görsel varlıklarız ve gerçek içgörünün elde edilebileceği durumlar vardır. Sandy McKee’nin bazı örneklerine buradan bakın. Yalnız biraz ihtiyat payı ile kullanın.
Şimdilik, bazı havalı şeyler için wordcloud2 adlı yeni bir pakete göz atın. Bu paket, html widget’ları oluşturan yaratıcı bir bulut koleksiyonu sunar. Hatta bir kelimenin üzerine gelerek metindeki sıklığını görebilirsiniz. (Bu paket rMarkdown’da yavaş render edebilir ve sıklıkla kullandığı tarayıcı konusunda seçicidir. Umarız geliştirmeler yapılır.)
Daha da eğlenceli olması için biraz veri sanatı ekleyebilirsiniz…
wordcloud2(prince_words_counts[1:300, ], figPath = "guitar_icon.png",
color = "random-dark", size = 1.5)
letterCloud(prince_words_counts[1:300, ], word = "PRINCE", size = 2)
Popüler Kelimeler
Şimdiye dek yalnızca tüm şarkılar boyunca en üst kelimeleri gördünüz. Peki bunları liste seviyesine göre ayırırsanız ne olur? Listelere giren şarkılarda bazı kelimeler, listeye girmeyen şarkılara göre daha mı yaygın? Bunlar toplum tarafından popüler görülen kelimelerdir.
Aşağıdaki kodda, her chart_level için ilk n kelimeyi almak üzere slice(seq_len(n)) kullanımına dikkat edin. Bu, top_n()’dan farklı çalışır ve grafiğinizde fasetleme kullanırken iyi bir seçimdir. (Böyle numaralar için her zaman farklı yollar olduğunu unutmayın.) Ayrıca, grafikte kelimeleri doğru sırada listeleyebilmek için row_number() işlevini kullanabilirsiniz. ggplot() varsayılan olarak kelimeleri alfabetik sıralar; grafikten önce sıralama yapmak iyi bir pratiktir.
popular_words <- prince_words_filtered %>%
group_by(chart_level) %>%
count(word, chart_level, sort = TRUE) %>%
slice(seq_len(8)) %>%
ungroup() %>%
arrange(chart_level,n) %>%
mutate(row = row_number())
popular_words %>%
ggplot(aes(row, n, fill = chart_level)) +
geom_col(show.legend = NULL) +
labs(x = NULL, y = "Şarkı Sayısı") +
ggtitle("Liste Seviyesine Göre Popüler Kelimeler") +
theme_lyrics() +
facet_wrap(~chart_level, scales = "free") +
scale_x_continuous( # This handles replacement of row
breaks = popular_words$row, # notice need to reuse data frame
labels = popular_words$word) +
coord_flip()
Buradan ne tür içgörüler çıkarıyorsunuz?
Görüldüğü gibi, liste seviyeleri genelinde en üst kelimeler birbirine çok, ama çok benziyor. Bu, bir şarkının başarısını yalnızca sözlere bakarak tahmin etme umutlarımız için pek iyi görünmüyor! Ancak metin madenciliğiyle mümkün olanların yalnızca yüzeyine dokundunuz ve sonunda NLP ile öngörücü modellemeye geçeceksiniz.
Zamansız Kelimeler
Müzikte bazı kelimeler zamansız kabul edilir. Zamansız kelimeler zaman içinde kalıcılığını korur ve geniş bir kitleye hitap eder. Analizinizi on yıllara göre bölerseniz, bu kelimeler zirveye çıkar. Prince’in sözlerinden her on yıl için en üst kelimeleri almak ve hangi kelimelerin zamansız ya da trend olduğunu görmek için filtreleme, gruplama ve toplulaştırmayı kullanın. On yıla göre görüntülemek için facet_wrap() ile ggplot() kullanabilirsiniz.
timeless_words <- prince_words_filtered %>%
filter(decade != 'NA') %>%
group_by(decade) %>%
count(word, decade, sort = TRUE) %>%
slice(seq_len(8)) %>%
ungroup() %>%
arrange(decade,n) %>%
mutate(row = row_number())
timeless_words %>%
ggplot(aes(row, n, fill = decade)) +
geom_col(show.legend = NULL) +
labs(x = NULL, y = "Şarkı Sayısı") +
ggtitle("Zamansız Kelimeler") +
theme_lyrics() +
facet_wrap(~decade, scales = "free", ncol = 5) +
scale_x_continuous( # This handles replacement of row
breaks = timeless_words$row, # notice need to reuse data frame
labels = timeless_words$word) +
coord_flip()
Açıkça görülüyor ki love, time ve girl zamansız. Peki trend olan kelimeleri saptamak ne kadar kolay? truth milenyumun başında trend miydi? Belki de yalnızca bazı şarkılarda çok tekrarlanan bir kelimedir? Sıklık gerçekten temaları tanımlar mı? Bu, Birliğin Durumu konuşmalarını analiz etmek gibi diğer metin madenciliği görevlerinde olduğu gibi şarkı sözlerinde de işe yarar mı?
Kelime Uzunluğu
Kelime uzunluğu, söz yazarları için ilginç bir konudur. Kelime ne kadar uzunsa, kafiyelendirmek ve bir kalıba sığdırmak o kadar zordur. Aşağıda gösterilen kelime uzunlukları histogramı beklendiği gibidir; birkaç inanılmaz uzun istisna ile.
#unnest and remove undesirable words, but leave in stop and short words
prince_word_lengths <- prince %>%
unnest_tokens(word, lyrics) %>%
group_by(song,decade) %>%
distinct() %>%
filter(!word %in% undesirable_words) %>%
mutate(word_length = nchar(word))
prince_word_lengths %>%
count(word_length, sort = TRUE) %>%
ggplot(aes(word_length),
binwidth = 10) +
geom_histogram(aes(fill = ..count..),
breaks = seq(1,25, by = 2),
show.legend = FALSE) +
xlab("Kelime Uzunluğu") +
ylab("Kelime Sayısı") +
ggtitle("Kelime Uzunluğu Dağılımı") +
theme(plot.title = element_text(hjust = 0.5),
panel.grid.minor = element_blank())
Bu çılgınca uzun kelimeler neler? Tamamen eğlencelik bir kelime bulutu zamanı! Bu, kelime sıklığı yerine kelime uzunluğuna dayanır. Göz atın:
Bir metnin söz varlığı ne kadar çeşitliyse, sözel çeşitliliği (lexical diversity) o kadar yüksektir. Şarkı Söz Varlığı, bir şarkıda kullanılan benzersiz kelime sayısının bir temsilidir. Bu, yıllara göre şarkı başına ortalama benzersiz kelimelerin basit bir grafiğiyle gösterilebilir. Bu grafikte niceliksel içgörülere daha çok baktığınız için, orijinal veri setini yeniden token’layacak ancak tüm stop ve kısa kelimeleri tutacaksınız.
Bu ne anlama geliyor? Son birkaç on yılda Prince’in söz çeşitliliğinde hafif bir yukarı yönlü eğilim vardı. Bu, liste başarısıyla nasıl ilişkilidir? Gerçekten söylemesi zor; ama karşılaştırma için yoğunluk ve liste geçmişini de çizelim.
Sözel Yoğunluk
Bu eğitim için sözel yoğunluğun, benzersiz kelime sayısının toplam kelime sayısına oranı olarak tanımlandığını hatırlayın. Bu, kelime tekrarının bir göstergesidir; bu da bir söz yazarının kritik bir aracıdır. Sözel yoğunluk arttıkça, tekrar azalır. (Not: bu, bir başka söz yazarlığı numarası olan ardışık tekrarı ima etmez.)
Prince’in yıllara göre sözel yoğunluğuna bir bakın. Yoğunluk için, stop kelimeler de dahil tüm kelimeleri tutmak en iyisidir. Bu nedenle, orijinal veri setiyle başlayıp kelimeleri unnest edin. Şarkı ve yıla göre gruplayın ve yoğunluğu hesaplamak için n_distinct() ve n() kullanın. Bunu geom_smooth() ile ggplot()’a aktarın. Doğrusal bir yumuşatma modeli için method="lm" ile ek bir stat_smooth() ekleyin.
Eğilimleri karşılaştırmak için, liste geçmişi (yani listelere giren başarılı şarkılar) için bir grafik oluşturun ve bunu çeşitlilik ve yoğunlukla kıyaslayın. gridExtra’dan grid.arrange() kullanarak yan yana çizin.
Yukarıdan, Prince’in sözel çeşitliliği ve yoğunluğunda yıllar içinde hafif bir artış olduğunu görüyorsunuz. Bu eğilim, tüm popüler müzikle nasıl karşılaştırılır? Bir çalışma, Hit Şarkılarda sözel yoğunluğun azaldığını, bunun da tekrarın arttığını (yani "daha az şey söyleyen daha çok kelime") gösterdiğini ortaya koyuyor. Prince’in şarkılarında olan bu değil. Bir diğer çalışma ise tüm popüler müzik genelinde çeşitliliğin (benzersiz kelimeler) zamanla arttığını ve bunun Prince’in müziğiyle olumlu yönde ilişkili olduğunu ortaya koyuyor. Bu, tarih boyunca liste sıralamalarında tür çeşitliliğinin artmasıyla ilişkili olabilir. Tür, bu veri setinde bulunmayan kritik bir veri parçası. Popüler müzik için liste geçmişi düşerken R&B/Rap için artıyor olabilir mi?
Öneri: Bu sonuçları düşünmenizi ve hatta bu becerileri kendi başınıza kullanabileceğiniz farklı veri setleri aramanızı teşvik ediyorum! Unutmayın, korelasyon nedenselliği ima etmez.
TF-IDF
Şimdiye kadar kullandığınız yöntem, tüm veri setine baktı; ancak bir bütün içinde çeşitli terimlerin bir belge için ne kadar önemli olduğunu sayısallaştırmayı ele almadı. Terim sıklığına baktınız ve stop kelimeleri kaldırdınız; ama bu en sofistike yaklaşım olmayabilir.
Karşınızda TF-IDF. TF "terim sıklığıdır" (term frequency). IDF ise "ters belge sıklığıdır" (inverse document frequency) ve yaygın kullanılan kelimelere daha düşük, koleksiyonda az kullanılan kelimelere daha yüksek ağırlık verir. TF ve IDF’yi birleştirdiğinizde, bir terimin önemi, ne kadar nadir kullanıldığına göre ayarlanır. TF-IDF’nin ardındaki varsayım, bir belgede daha sık görünen terimlerin daha yüksek ağırlık alması gerektiğidir; ta ki pek çok belgede de görünmüyorsa. Formül özetle şöyle verilebilir:
Terim Sıklığı (TF): Bir belgede bir terimin geçme sayısı
Belge Sıklığı (DF): Her kelimeyi içeren belge sayısı
Ters Belge Sıklığı (IDF) = 1/DF
TF-IDF = TF * IDF
Dolayısıyla, bir koleksiyondaki belgelerin daha azında görülen kelimeler için herhangi bir terimin IDF’si daha yüksek bir sayıdır. tidytext’in sağladığı bind_tf_idf() işleviyle, liste seviyesi başına en önemli kelimeleri incelemek için bu yeni yaklaşımı kullanabilirsiniz. Bu işlev, TF ve IDF’yi hesaplar ve TF*IDF çarpımıyla birlikte bağlar. Girdi olarak, belge (şarkı) başına token (kelime) başına bir satır içeren tidy bir metin veri seti alır. Sonuçları yeni sütunlarda göreceksiniz.
Öyleyse, orijinal Prince veri çerçevenizi alın ve token’ları kelimelere açın, istenmeyen kelimeleri kaldırın; ancak stop kelimeleri tutun. Sonra bind_tf_idf() kullanarak formülleri çalıştırın ve yeni sütunlar oluşturun.
## # A tibble: 6 x 6
## chart_level word n tf idf tf_idf
## <chr> <chr> <int> <dbl> <dbl> <dbl>
## 1 Uncharted that 622 0.010942420 0 0
## 2 Uncharted your 529 0.009306335 0 0
## 3 Uncharted what 496 0.008725789 0 0
## 4 Uncharted will 481 0.008461904 0 0
## 5 Uncharted this 464 0.008162834 0 0
## 6 Uncharted know 441 0.007758211 0 0
Şimdi, çok yaygın kelimeler için IDF ve TF-IDF’nin 0 olduğunu görebilirsiniz. (Teknik olarak, IDF terimi doğal logaritmada 1 olur ve bu nedenle bu kelimeler için sıfırdır.) Yukarıdaki sonuçlarınızı arrange() içine aktarın ve tf-idf’ye göre azalan şekilde sıralayın. Birkaç adım daha ekleyin ve Prince’in sözlerindeki kelimelere bakmanın farklı bir yolunu göreceksiniz.
top_popular_tfidf_words <- popular_tfidf_words %>%
arrange(desc(tf_idf)) %>%
mutate(word = factor(word, levels = rev(unique(word)))) %>%
group_by(chart_level) %>
slice(seq_len(8)) %>%
ungroup() %>%
arrange(chart_level, tf_idf) %>%
mutate(row = row_number())
top_popular_tfidf_words %>%
ggplot(aes(x = row, tf_idf,
fill = chart_level)) +
geom_col(show.legend = NULL) +
labs(x = NULL, y = "TF-IDF") +
ggtitle("Liste Seviyesine Göre TF-IDF ile Önemli Kelimeler") +
theme_lyrics() +
facet_wrap(~chart_level, ncol = 3, scales = "free") +
scale_x_continuous( # This handles replacement of row
breaks = top_popular_tfidf_words$row, # notice need to reuse data frame
labels = top_popular_tfidf_words$word) +
coord_flip()
Vay canına, TF-IDF kullanmak potansiyel olarak önemli kelimelere bambaşka bir bakış açısı sunuyor. Elbette yorum tamamen öznel. Herhangi bir desen fark ettiniz mi?
Şimdi de TF-IDF’ye zamana göre bakın:
tfidf_words_decade <- prince %>%
unnest_tokens(word, lyrics) %>%
distinct() %>%
filter(!word %in% undesirable_words & decade != 'NA') %>%
filter(nchar(word) > 3) %>%
count(decade, word, sort = TRUE) %>%
ungroup() %>%
bind_tf_idf(word, decade, n) %>%
arrange(desc(tf_idf))
top_tfidf_words_decade <- tfidf_words_decade %>%
group_by(decade) %>%
slice(seq_len(8)) %>%
ungroup() %>%
arrange(decade, tf_idf) %>%
mutate(row = row_number())
top_tfidf_words_decade %>%
ggplot(aes(x = row, tf_idf, fill = decade)) +
geom_col(show.legend = NULL) +
labs(x = NULL, y = "TF-IDF") +
ggtitle("On Yıla Göre TF-IDF ile Önemli Kelimeler") +
theme_lyrics() +
facet_wrap(~decade,
ncol = 3, nrow = 2,
scales = "free") +
scale_x_continuous( # this handles replacement of row
breaks = top_tfidf_words_decade$row, # notice need to reuse data frame
labels = top_tfidf_words_decade$word) +
coord_flip()
Şimdi kesinlikle daha derin bir içgörü düzeyi elde ediyorsunuz. Zamansız kelimeler artık baskın değil. Konular veya temalar belirmeye başladı mı? Gerçekten yalnızca grup başına birkaç kelimeyle mümkün mü? Bunu ikinci eğitimde (İkinci Bölüm: NLP ile Duygu Analizi ve Konu Modellemesi) yeni boyutlara taşıyacaksınız.
Bu yöntemle hızlı bir kelime bulutu, Prince’in sözlerindeki önemli kelimelere yeni bir bakış sunar ve biraz daha ilgi çekicidir…
Bu vaka çalışmasında önce, yalnızca temel unsurlara bakarak gerçek veriye bir göz attınız. Veri temizleme ve bilgilendirici olmayan kelimeleri kaldırma gibi bazı koşullandırmalar yaptıktan sonra, şarkı düzeyinde keşifsel bir analize başladınız.
Ardından, sözleri token’lanmış kelimelere ayırarak sözel karmaşıklığa bakabilmek için metin madenciliğine daha derinlemesine girdiniz. Sonuçlar, bir sonraki adımlar olan duygu analizi ve konu modellemesi için kritik içgörüler sağlar.
Son olarak, bir belgede bir kelimenin, ilgi duyulan bir sonuçla ilişkili bilgisini temsil etmek için TF-IDF analizini kullandınız. Bunun müzikte temaları belirlemenin iyi bir yolu olduğunu düşünebilirsiniz; ama hikâyenin yalnızca yarısına sahipsiniz. İkinci Bölüm, Gizli Dirichlet Ayrımı (LDA) adlı gözetimsiz bir öğrenme yöntemini ele alır. Veri Bilimi’nin her alanında olduğu gibi, içgörü kazanmak için seçebileceğiniz pek çok yöntem vardır. Bu vaka çalışmasının İkinci ve Üçüncü Bölümlerinde bu seçeneklerden daha fazlasını ele alacaksınız.
Umarım, keşifsel analizden duygu analizine, konu modellemesine ve öngörücü içgörülere uzanan bu yolculuğa benim kadar siz de heyecanlısınızdır.
Okuduğunuz için teşekkürler; bir sonraki eğitimde görüşmek üzere!
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!
Bu, efsanevi sanatçı Prince’in şarkı sözleri üzerine bir vaka çalışmasında R kullanarak çeşitli analitik görevler yapacağınız, üç bölümlük bir eğitim serisinin Birinci Bölümü. Üç eğitim şu konuları kapsar:
Giriş
Müzik sözleri bir sanatçının bakış açısını yansıtabilir, ancak popüler şarkılar toplumun duymak istediklerini ortaya koyar. Şarkı sözü analizi kolay bir iş değildir. Düz yazıdan çok farklı yapılandığı için varsayımlarda dikkatli olmayı ve özgün bir analitik teknik seçimini gerektirir. Şarkı sözleri hayatımıza sızar ve düşüncelerimizi fark edilmeden etkiler. Öngörücü Şarkı Sözleri kavramı yeni yeni konuşulmaya başlandı ve araştırma makaleleri ile lisansüstü tezlerde giderek daha çok yer buluyor. Bu vaka çalışması, bu gelişmekte olan konunun yalnızca birkaç yönüne değinecek.
Prince: Sanatçı
Prince’in geride bıraktığı ilham verici ve çeşitli eserlerini kutlamak için, sözlerinde bazen açık, çoğu zaman gizli mesajları keşfedeceksiniz. Yine de, dünya çapında pek çok türün gelişimindeki etkisini takdir etmek için Prince’in müziğini sevmeniz gerekmez. Rolling Stone dergisi, Prince’i tüm zamanların en iyi 18. söz yazarı olarak, Bob Dylan, John Lennon, Paul Simon, Joni Mitchell ve Stevie Wonder gibi isimlerin hemen arkasında listeler. Şarkı sözü analizi, "Hit Şarkıları" öngörme olasılığı gerçeğe yaklaşırken yavaş yavaş veri bilimi topluluklarında yer buluyor.
Bu eğitimin, serinin Birinci Bölümü olan kısmında, tidy text çerçevesini kullanarak bir dizi şarkı sözü üzerinde metin madenciliği tekniklerinden yararlanacaksınız. Tidy veri setlerinin belirli bir yapısı vardır: her değişken bir sütun, her gözlem bir satır ve her gözlemsel birim türü bir tablodur. Veri setini temizleyip koşullandırdıktan sonra, Prince’in şarkı sözlerinin farklı yönlerine bakarken betimsel istatistikler ve keşifsel görselleştirmeler oluşturacaksınız.
Önkoşullar
Bu eğitim serisinin Birinci Bölümü, tidy veriye ilişkin temel bir anlayış gerektirir — özellikle veri dönüşümü için dplyr, görselleştirmeler için ggplot2 ve kökeni magrittr paketine dayanan %>% pipe operatörü gibi paketler. Her eğitim, analizinizde kullanabileceğiniz araçları tanıtacak, ancak her adımı ayrıntılandırmayabilir. Birçok adımın genellikle %>% operatörüyle birleştirildiğini fark edeceksiniz. Bu aynı zamanda bir vaka çalışması olduğundan, yaptığınız tüm çıkarımların tamamen gözlemsel olduğunu unutmamak önemlidir; dolayısıyla, korelasyon nedenselliği ima etmez.
İpucu: kullanılan araçlar hakkında arka plan için iki iyi kaynak: Garrett Grolemund ve Hadley Wickham’ın R for Data Science’ı; ve Julia Silge ile David Robinson’ın Text Mining with R’ı.
İkinci ve Üçüncü Bölümler
Ayrı bir eğitim olan İkinci Bölüm’de, Prince’in müziğindeki genel ruh halini ve temaları ve bunların toplumsal bakış açılarına uygulanışını yakalamak için Duygu Analizi ve Konu Modellemesini ele alacaksınız. Bir duygu sözlüğü ile çalışacak, ikili ve kategorik duyguları değerlendirecek, zaman içindeki eğilimleri çizecek ve n-gram’lar ile sözcük birlikteliklerine bakacaksınız. Ayrıca Doğal Dil İşleme (NLP) ve Gizli Dirichlet Ayrımı (LDA) ile K-Ortalamalar gibi kümeleme tekniklerini kullanarak sözlerdeki motifleri ortaya çıkaracaksınız.
Bir diğer eğitim olan Üçüncü Bölüm’de ise, keşifsel sonuçlarınızı kullanarak bir şarkının hangi on yılda yayımlandığını ve daha da ilginci, yalnızca sözlerine bakarak Billboard listelerine girip girmeyeceğini tahmin etmeye çalışarak işi tamamlayacaksınız. Karar Ağaçları (rpart ve C50), En Yakın K-Komşular (class) ve Naive Bayes (e1071) gibi makine öğrenimi araçlarını kullanarak metin kabul edebilen bir sınıflandırıcı üreteceksiniz.
Üç bölümün tamamı, Prince’in şarkı sözleri, yayımlanma yılı ve Billboard liste konumlarından oluşan aynı veri setini kullanacaktır. Bu çalışmadaki teknikler, pek çok başka metin türüne de uygulanabilir. Aslında, standart düzyazı için sonuçlar genellikle daha kolay yorumlanır çünkü şarkı sözleri genel olarak dolaylı mesajlar ve ince nüanslarla tasarlanır.
Özetle, şarkı sözlerini analiz etmek için birçok farklı yöntem vardır. Bu eğitimler, aşağıdaki görselde kırmızıyla vurgulananları kapsar. Bu görselin çok "bulanık" bir resmin yalnızca üst düzey bir temsil olduğunu unutmayın. Ve hayır, kastettiğim görselin kendisi değil! Gerçek şu ki, modelleme ve makine öğrenimi tekniklerinin farklı yönleri artık bulanıklaşmış durumda ve aşağıda gösterildiği gibi tek bir kutuya sığmayabiliyor. Bu yüzden görsele bakarken 3D gözlükleri takın; belki daha anlamlı gelir!
Hedefler
Yeni beceriler öğrenip pratiğini yapmanın yanı sıra, bu eğitim şarkı sözü analizi kavramıyla ilgili temel soruları ele almayı amaçlar. Son çalışmalar, popüler müzikte "sözel zekânın" düşüşte olabileceğini gösteriyor. Bazı çalışmalar, 1 Numaralı Hit Şarkılarda kullanılan kelimelerin ABD’de 3. sınıf öğrencilerinin okuma seviyeleriyle örtüştüğünü dahi öne sürüyor. Böyle bir konuya ışık tutmak için metin madenciliği, NLP, makine öğrenimi ve diğer veri bilimi yöntemlerinden yararlanmak mümkün mü? Bir şarkının nasıl karşılandığına bağlı olarak topluma hitap eden temaları belirlemek mümkün mü? Sadece söz analizine dayanarak bir şarkının başarılı olup olmayacağını tahmin etmek mümkün mü? Bu ilk eğitimde, Prince’in müziğinin sözel karmaşıklığını keşif amaçlı inceleyeceksiniz.
Sorular
Dalmadan önce, neyi keşfetmeye çalıştığınızı düşünün. Hangi sorular ilginizi çekiyor? Önce veri setinin bir analizini adım adım yapacaksınız. Nasıl görünüyor? Kaç şarkı var? Sözler nasıl yapılandırılmış? Ne kadar temizlik ve düzenleme gerekiyor? Gerçekler neler? Kelime sıklıkları nedir ve bu neden önemli? Teknik açıdan, veriyi duygu analizi, NLP ve makine öğrenimi modelleri için anlamak ve hazırlamak istersiniz.
Veri
Metin madenciliği için veri elde etmenin popüler bir yöntemi, rvest paketini kullanarak web’den içerik kazımaktır. Billboard Liste bilgilerini ve Prince’in şarkı sözlerini çeşitli sitelerden kazıyıp şarkı başlıklarında birleştirebildim. Başlıklar için tutarsız adlandırma kuralları olduğundan biraz düzenleme gerekti. Ardından, orijinal sürüm olmayan, yani remiksler, uzatılmış sürümler, kulüp miksleri, yeniden yapımlar vb. tüm şarkıları kaldırma yönünde öznel bir karar verdim. Ayrıca tekrarları önlemek için Hit Şarkılarının tarihsel derlemelerini içeren albümleri de çıkardım. Biraz küçük temizlik yapıp sonucu bu eğitimde kullanılabilecek bir csv dosyasına kaydettim.
Birinci Bölüm metin madenciliğine odaklandığından, bu eğitim için o kodu dahil etmedim; ancak veri setini indirmek isterseniz buradan erişebilirsiniz.
Kütüphaneleri yükleyin
Veriyi içe alın
Bir csv dosyasından veri okumak için birkaç yöntem vardır, ancak ben sözleri, yayımlanma yılını ve Billboard liste konumlarını içeren bir veri çerçevesi yüklemek için read.csv() kullanmayı seçtim. Varsayılan olarak R’nin tüm karakter dizilerini faktöre dönüştürdüğüne dikkat edin. Bu, sonraki adımlarda sorun yaratabilir; fakat stringsAsFactors parametresini FALSE yaparak bunu önleyebilirsiniz. Şimdi veriyi inceleyelim…
prince_orig <- read.csv("prince_raw_data.csv", stringsAsFactors = FALSE)Veri çerçevesindeki sütunları görmek için names() işlevini kullanabilirsiniz:
Bu dosyayı ben oluşturduğum için X’in yalnızca bir satır numarası, text’in ise gerçek şarkı sözleri olduğunu biliyorum. Diğer gerekli alanlar arasında şarkı (song), yıl (year) ve Billboard listelerindeki yerini gösteren peak bulunur. US.Pop ve US.R.B, ABD (Pop ve R&B listeleri) için zirve liste konumlarıdır; bunları da koruyun ve şimdilik diğer tüm alanları bırakın.
Bunu, orijinal veri seti olan prince_orig’i alıp %>% ile select()’e aktararak yapın. Böylece kodu soldan sağa okuyabilirsiniz.
Ayrıca, select()’in sütunları tek adımda yeniden adlandırmanıza izin verdiğine dikkat edin. Dolayısıyla text’i lyrics olarak ayarlayın ve US sütunlarını "." yerine "_" kullanarak tidyverse tarzında yeniden adlandırın. Ardından sonucu, eğitim boyunca kullanacağınız prince içinde saklayın. dplyr, verinize transpoze bir görünümde bakmayı kolaylaştıran glimpse() adlı bir işlev sağlar.
prince <- prince_orig %>% select(lyrics = text, song, year, album, peak, us_pop = US.Pop, us_rnb = US.R.B) glimpse(prince[139,])İlk açık soru: kaç gözlem ve kaç sütun var?
dim() işlevini kullanarak 7 sütun ve 824 gözlem olduğunu görürsünüz. Her gözlem bir şarkıdır. Dediğim gibi… üretken!
Şarkılardan birinin lyrics sütununa baktığınızda, yapının nasıl olduğunu görebilirsiniz.
Temizlemek için bolca fırsat var, hadi başlayalım.
Veri Koşullandırma
Temel temizlik
Veriyi koşullandırmak için kullanabileceğiniz farklı yöntemler vardır. Bir seçenek, veri çerçevesini tm metin madenciliği paketiyle bir Korpus ve Belge Terim Matrisi’ne dönüştürmek ve ardından temizlik için tm_map() işlevini kullanmaktır; ancak bu eğitim şimdilik temel konularla sınırlı kalacak ve kirli işleri yapmak için gsub() ve apply() işlevlerini kullanacaktır.
Önce, gsub() kullanarak çoğu senaryoyu ele alan küçük bir işlev oluşturarak o can sıkıcı kısaltmalardan kurtulun ve ardından bu işlevi tüm şarkı sözlerine uygulayın.
# function to expand contractions in an English-language source fix.contractions <- function(doc) { # "won't" is a special case as it does not expand to "wo not" doc <- gsub("won't", "will not", doc) doc <- gsub("can't", "can not", doc) doc <- gsub("n't", " not", doc) doc <- gsub("'ll", " will", doc) doc <- gsub("'re", " are", doc) doc <- gsub("'ve", " have", doc) doc <- gsub("'m", " am", doc) doc <- gsub("'d", " would", doc) # 's could be 'is' or could be possessive: it has no expansion doc <- gsub("'s", "", doc) return(doc) } # fix (expand) contractions prince$lyrics <- sapply(prince$lyrics, fix.contractions)Metni bulanıklaştıran özel karakterleri de fark edeceksiniz. Bunları gsub() işlevi ve basit bir düzenli ifadeyle kaldırabilirsiniz. Dikkat: Bu adımdan önce kısaltmaları genişletmek kritik önemdedir!
# function to remove special characters removeSpecialChars <- function(x) gsub("[^a-zA-Z0-9 ]", " ", x) # remove special characters prince$lyrics <- sapply(prince$lyrics, removeSpecialChars)Tutarlılık için, kullanışlı tolower() işleviyle her şeyi küçük harfe dönüştürün.
Şimdi sözleri incelediğinizde, orijinal ham metnin daha temiz bir sürümünü görürsünüz.
Metin madenciliği için veriyi koşullandırmadaki bir diğer yaygın adım, kelimeleri kök anlamlarına indirgeme ya da gövdeleme (stemming) olarak adlandırılır. Bu başlı başına bir konu olup daha sonra ele alınabilir. Şimdilik, prince veri çerçevesinin özetine bakın.
lyrics song year album Length:824 Length:824 Min. :1978 Length:824 Class :character Class :character 1st Qu.:1989 Class :character Mode :character Mode :character Median :1996 Mode :character Mean :1995 3rd Qu.:1999 Max. :2015 NA's :495 peak us_pop us_rnb Min. : 0.00 Length:824 Length:824 1st Qu.: 2.00 Class :character Class :character Median : 7.00 Mode :character Mode :character Mean :15.48 3rd Qu.:19.00 Max. :88.00 NA's :751Gördüğünüz gibi, 37 yıllık şarkı var ve (veri setinde bulunan) en düşük listeye giren şarkı 88. sırada. Ayrıca yıl ve peak için oldukça fazla NA olduğunu da görebilirsiniz. Farklı türde analizler yapacağınız için, tam veri setini prince veri çerçevesinde tutun ve gerektiğinde filtreleyin.
Birkaç alan ekleyin
Hedef sorularınızdan biri zaman içinde şarkı eğilimlerine bakmak olduğundan ve veri setinde tek tek yayımlanma yılları bulunduğundan, yılları on yıllık dilimlere (bucket) ayırabilirsiniz. dplyr’ın mutate() fiilini kullanarak yeni decade alanını oluşturun. Dilimleri oluşturmanın bir yolu, ifelse() ile %in% operatörünü birlikte kullanarak yıllara göre filtreleme ve şarkıları on yıllara göre gruplamaktır. Sonra sonuçları tekrar prince içine yazın (özünde yeni bir alan eklemiş olursunuz).
#create the decade column prince <- prince %>% mutate(decade = ifelse(prince$year %in% 1978:1979, "1970s", ifelse(prince$year %in% 1980:1989, "1980s", ifelse(prince$year %in% 1990:1999, "1990s", ifelse(prince$year %in% 2000:2009, "2000s", ifelse(prince$year %in% 2010:2015, "2010s", "NA"))))))Aynısını, bir şarkının Top 10, Top 100’e ulaşıp ulaşmadığını ya da listeye hiç girmediğini (uncharted) ifade eden chart_level için de yapabilirsiniz. Bunlar birbirini dışlar; dolayısıyla Top 100, Top 10 şarkıları içermez.
#create the chart level column prince <- prince %>% mutate(chart_level = ifelse(prince$peak %in% 1:10, "Top 10", ifelse(prince$peak %in% 11:100, "Top 100", "Uncharted")))Ayrıca, bir şarkının Billboard listelerine girip girmediğini gösteren charted adlı ikili bir alan oluşturun (yani popüler bir şarkı). Sonraki eğitimlerde kullanmak üzere write.csv() ile kaydedin.
#create binary field called charted showing if a song hit the charts at all prince <- prince %>% mutate(charted = ifelse(prince$peak %in% 1:100, "Charted", "Uncharted")) #save the new dataset to .csv for use in later tutorials write.csv(prince, file = "prince_new.csv")Betimsel İstatistikler
Grafikleri özelleştirmek için, görsellerin tutarlı kalması adına benzersiz bir renk listesi oluşturmayı seviyorum. Aşağıdaki gibi onaltılık kod temsilleriyle ayırt edilebilir renkler bulabileceğiniz birçok web kaynağı var. Grafikleriniz için bir tercihiniz varsa, gerektiğinde ggplot()’a uygulayabileceğiniz kendi temanızı da oluşturabilirsiniz.
#define some colors to use throughout my_colors <- c("#E69F00", "#56B4E9", "#009E73", "#CC79A7", "#D55E00") theme_lyrics <- function() { theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_blank(), axis.ticks = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), legend.position = "none") }Metin madenciliğine girmeden önce, verinizin şarkı düzeyinde neler barındırdığına dair temel bir görünümle başlayın. Prince’in on yıllara göre kaç şarkı yayımladığını görselleştirmek için iyi bir zaman. Hatırlatma: profesyonel kariyeri 1978’de başladı ve 2015’e kadar sürdü (yukarıdaki summary() istatistiklerinde gösterildiği gibi). Ancak şimdi eğilimlere baktığımız ve veri setinde yıl için çok sayıda boş değer olduğu için, ilk grafikte yayımlanma yılı NA olanların tümünü filtrelemek isteyeceksiniz.
Şarkı İstatistikleri
dplyr’ın filter(), group_by() ve summarise() işlevlerini kullanarak on yıla göre gruplama yapabilir ve ardından şarkı sayısını sayabilirsiniz. n() işlevi, gruplandırılmış verilerde summarise() ile kullanımı yararlı birkaç toplulaştırma işlevinden biridir. Sonra ggplot() ve geom_bar() kullanarak bir çubuk grafik oluşturun ve çubukları charted kategorisine göre doldurun.
prince %>% filter(decade != "NA") %>% group_by(decade, charted) %>% summarise(number_of_songs = n()) %>% ggplot() + geom_bar(aes(x = decade, y = number_of_songs, fill = charted), stat = "identity") + theme(plot.title = element_text(hjust = 0.5), legend.title = element_blank(), panel.grid.minor = element_blank()) + ggtitle("Yayımlanan Şarkılar") + labs(x = NULL, y = "Şarkı Sayısı")Bu, en üretken on yılının 1990’lar olduğunu açıkça gösteriyor.
Şimdi chart_level ile benzer bir grafik oluşturun.
Eğilimi görebilmek için hem decade hem chart_level ile group_by() yapmayı unutmayın.
Bu grafikte yalnızca listeye giren şarkılara bakacağınız için peak > 0 kullanarak diğer her şeyi filtreleyin. group_by nesnesini n() ile şarkı sayısını saymak üzere summarise()’a aktarın. Bunu bir değişkende saklarken, basit bir çubuk grafik için ggplot()’a da aktarabilirsiniz.
charted_songs_over_time <- prince %>% filter(peak > 0) %>% group_by(decade, chart_level) %>% summarise(number_of_songs = n()) charted_songs_over_time %>% ggplot() + geom_bar(aes(x = decade, y = number_of_songs, fill = chart_level), stat = "identity") + theme(plot.title = element_text(hjust = 0.5), legend.title = element_blank(), panel.grid.minor = element_blank()) + labs(x = NULL, y = "Şarkı Sayısı") + ggtitle("Listeye Giren Şarkılar")İçgörüler
Prince’in listeye giren tüm şarkıları içinde çoğunluğun Top 10’a ulaştığına dikkat edin. Ama daha da ilginci, yeni şarkılar açısından en üretken on yılı 1990’lar olmasına rağmen, daha çok liste başarısı 1980’lerde yaşanmış. Neden? Metin madenciliği bölümlerini incelerken bu soruyu aklınızda tutun.
Şarkı sözü analizi için tam veri setinin gücünden yararlanmak üzere, liste seviyesi ve yayımlanma yılına dair referansları kaldırarak madencilik yapabileceğiniz çok daha büyük bir şarkı kümesine sahip olabilirsiniz. Bir bakın:
#look at the full data set at your disposal prince %>% group_by(decade, chart_level) %>% summarise(number_of_songs = n()) %>% ggplot() + geom_bar(aes(x = decade, y = number_of_songs, fill = chart_level), stat = "identity") + theme(plot.title = element_text(hjust = 0.5), legend.title = element_blank(), panel.grid.minor = element_blank()) + labs(x = NULL, y = "Şarkı Sayısı") + ggtitle("Verideki Tüm Şarkılar")Gördüğünüz gibi, veride yayımlanma tarihi olmayan yüzlerce Prince şarkısı var. Duygu analizi veya keşifsel analiz için tüm veriyi kullanabilirsiniz; ancak zaman içindeki eğilimler için çalışabileceğiniz çok daha küçük bir küme kalır. Bu sorun değil — yalnızca akılda tutulması gereken bir nokta.
1 Numaralı Şarkılar!
Sıkı Prince hayranları için, listelerde 1 Numara olan şarkılara hızlı bir bakış aşağıda. (knitr ve kableExtra paketlerinden kable() ve kable_styling() ile formattable’dan color_tile() kullanarak güzel biçimlendirilmiş HTML çıktı oluşturabileceğinizi unutmayın.)
library(knitr) # for dynamic reporting library(kableExtra) # create a nicely formated HTML table library(formattable) # for the color_tile function prince %>% filter(peak == "1") %>% select(year, song, peak) %>% arrange(year) %>% mutate(year = color_tile("lightblue", "lightgreen")(year)) %>% mutate(peak = color_tile("lightgreen", "lightgreen")(peak)) %>% kable("html", escape = FALSE, align = "c", caption = "Prince's No. 1 Songs") %>% kable_styling(bootstrap_options = c("striped", "condensed", "bordered"), full_width = FALSE)Metin Madenciliği
Metin madenciliği, metin analitiği olarak da düşünülebilir. Amaç, muhtemelen bilinmeyen ya da bariz olanın altında gömülü kalmış ilgili bilgileri keşfetmektir. Doğal Dil İşleme (NLP), metin madenciliğinde kullanılan yöntemlerden biridir. Yazılı dildeki belirsizlikleri çözmek için tokenizasyon, kümeleme, varlık ve kelime ilişkilerini çıkarma ve temaları belirlemek ile öznel bilgileri nicelleştirmek için algoritmalar kullanır. Sözel karmaşıklık kavramını parçalayarak başlayacaksınız.
Sözel karmaşıklık farklı bağlamlarda farklı şeyler ifade edebilir; ancak şimdilik, şu ölçülerin birleşimiyle tanımlanabileceğini varsayalım:
Tidy Metin Biçimi
Analize başlamak için, şarkı sözlerini tek tek kelimelere ayırmanız ve içgörü madenciliğine başlamanız gerekir. Bu işleme tokenizasyon denir.
Veri Biçimleri ve Tokenizasyon
Metin madenciliğinde kullanılabilecek farklı yöntemler ve veri biçimleri olduğunu unutmayın:
Ancak herhangi bir tokenizasyondan önce, veriyi temizlemede bir adım daha var. Birçok şarkı sözü, yazıya dökülürken "Repeat Chorus" gibi ifadeler veya "Bridge" ve "Verse" gibi etiketler içerir. Sonuçları bulanıklaştırabilecek başka istenmeyen kelimeler de çoktur. Ön analiz yaptıktan sonra, aradan çıkarmak istediğim birkaçını seçtim.
Aşağıda, elle kaldırılması gereken gereksiz kelimelerin bir listesi bulunuyor:
undesirable_words <- c("prince", "chorus", "repeat", "lyrics", "theres", "bridge", "fe0f", "yeah", "baby", "alright", "wanna", "gonna", "chorus", "verse", "whoa", "gotta", "make", "miscellaneous", "2", "4", "ooh", "uurh", "pheromone", "poompoom", "3121", "matic", " ai ", " ca ", " la ", "hey", " na ", " da ", " uh ", " tin ", " ll", "transcription", "repeats")Token’ları açmak için, zaten yüklenmiş olan tidytext kütüphanesini kullanın. Artık dplyr’ın yeteneklerinden yararlanabilir ve birkaç adımı birleştirebilirsiniz.
Tidy metin çerçevesinden, hem metni tekil token’lara (tokenizasyon) bölmeniz hem de tidy bir veri yapısına dönüştürmeniz gerekir. Bunu yapmak için tidytext’in unnest_tokens() işlevini kullanın. unnest_tokens(), en az iki argüman gerektirir: metin çözülürken oluşturulacak çıktı sütununun adı (bu durumda "word") ve mevcut metni tutan girdi sütunu (ör. lyrics).
prince veri setini alıp unnest_tokens()’a aktarabilir ve ardından durdurma (stop) kelimelerini kaldırabilirsiniz. Stop kelimeler nelerdir? Çok iyi bildiğiniz, sonuçlarımıza anlam katmayabilecek kadar yaygın kelimelerdir. Seçilebilecek farklı listeler vardır; burada tidytext paketindeki stop_words sözlüğünü kullanacaksınız.
Bu stop kelimelerden rastgele bir liste göstermek için sample(), 15 kelimeyle sınırlamak için head() kullanın.
Dolayısıyla, şarkı sözlerini kelimelere ayırdıktan sonra, dplyr’ın anti_join() işlevini kullanarak stop kelimeleri kaldırabilirsiniz. Ardından, önceden tanımlanan istenmeyen kelimelerden dplyr’ın filter() fiili ve %in% operatörü ile kurtulun. Sonra yinelenen kayıtları kaldırmak için distinct() kullanın. Son olarak, dört karakterden kısa tüm kelimeleri kaldırabilirsiniz. Bu da öznel bir karardır; ancak sözlerde bunlar çoğunlukla "yea ve hey" gibi ünlemlerdir. Sonuçları prince_words_filtered içine kaydedin.
Not: gelecekte başvurmak üzere, prince_words_filtered; 1) stop kelimeler, 2) istenmeyen kelimeler ve 3) 1-3 karakterli kelimeler olmadan prince veri çerçevesinin tidy metin sürümüdür. Bunu bazı analizlerde kullanacak, bazılarında kullanmayacaksınız.
stop_words’un bir word sütunu olduğunu ve unnest_tokens() tarafından word adlı yeni bir sütun oluşturulduğunu fark edin; dolayısıyla anti_join() otomatik olarak word sütununda birleştirir.
Artık yeni tidy veri yapınızın sınıfını ve boyutlarını inceleyebilirsiniz:
prince_words_filtered, toplam 36916 kelime (benzersiz olmayan) ve 10 sütundan oluşan bir veri çerçevesidir. İşte bir anlık görüntü: (Sadece bir kelime seçip 10 şarkıdaki görünümlerini sınırladım ve ilgi çekici alanları sırayla yazdırmak için select() kullandım; yine biçimlendirme için knitr kullandım). Bu size token’lanmış, özetlenmemiş, tidy veri yapısını gösterir.
prince_words_filtered %>% filter(word == "race") %>% select(word, song, year, peak, decade, chart_level, charted) %>% arrange() %>% top_n(10,song) %>% mutate(song = color_tile("lightblue","lightblue")(song)) %>% mutate(word = color_tile("lightgreen","lightgreen")(word)) %>% kable("html", escape = FALSE, align = "c", caption = "Tokenized Format Example") %>% kable_styling(bootstrap_options = c("striped", "condensed", "bordered"), full_width = FALSE)Her satırın, göründüğü her şarkı için yinelenecek tek bir kelime içerdiğini görebilirsiniz.
Kelime Sıklığı
Müzikte, tek tek kelime sıklıkları ister tekrar ister nadirlik olsun büyük önem taşır. Her ikisi de şarkının akılda kalıcılığını etkiler. Bir söz yazarı bilmek isteyebilir: kelime sıklığı ile hit şarkılar arasında bir ilişki var mı? Şimdi, tidy biçimi bir adım daha ileri götürüp şarkı başına kelime sayısının özetlenmiş dökümünü elde etmek istiyorsunuz.
Prince’in sözlerinde bu biçimi incelemek için, Billboard Listelerindeki konuma göre şarkı bazında gruplanmış kelime sayımı dağılımını gösteren bir histogram oluşturun. Gerçek bir kelime sıklığı sayımı elde etmek için prince sözlerini, hiçbir kelimeyi filtrelemeden tekrar unnest edin. Yine group_by() ve summarise() kullanarak sayımları alın. Ardından, dplyr’ın arrange() fiilini kullanarak sayıya göre sıralayın. Önce en yüksek sayılara bakın, sonra histogram için ggplot() kullanın.
full_word_count <- prince %>% unnest_tokens(word, lyrics) %>% group_by(song,chart_level) %>% summarise(num_words = n()) %>% arrange(desc(num_words)) full_word_count[1:10,] %>% ungroup(num_words, song) %>% mutate(num_words = color_bar("lightblue")(num_words)) %>% mutate(song = color_tile("lightpink","lightpink")(song)) %>% kable("html", escape = FALSE, align = "c", caption = "Songs With Highest Word Count") %>% kable_styling(bootstrap_options = c("striped", "condensed", "bordered"), full_width = FALSE)full_word_count %>% ggplot() + geom_histogram(aes(x = num_words, fill = chart_level )) + ylab("Song Count") + xlab("Word Count per Song") + ggtitle("Word Count Distribution") + theme(plot.title = element_text(hjust = 0.5), legend.title = element_blank(), panel.grid.minor.y = element_blank())Sağa çarpık olduğuna dikkat edin. Şarkı sözü dökümünün doğası gereği, veri girişi hatalarından şüpheliyim. O yüzden, meraktan, 800’ün üzerinde kelimeye sahip o Top 10 şarkıya bir göz atın.
full_word_count %>% filter(chart_level == 'Top 10' & num_words > 800) %>% left_join(prince_orig, by = "song") %>% select(Song = song, "Word Count" = num_words, "Peak Position" = peak, "US Pop" = US.Pop, "US R&B" = US.R.B, Canada = CA, Ireland = IR) %>% kable("html", escape = FALSE) %>% kable_styling(bootstrap_options = c("striped", "condensed", "bordered"))Biraz araştırma yaptım ve bu şarkıda rap bölümü icra eden bir konuk sanatçı olduğunu keşfettim. Bu da durumu açıklıyor! Bu veri setinin dünya genelinde Pop ve R&B listelerini kapsadığını unutmayın; dolayısıyla tür ve coğrafya varsayımlarınızı büyük ölçüde etkileyebilir. Örneğin, Kanada’da 5’e kadar yükselmesine karşın, ABD Pop listesi sıralamasının çok daha düşük olduğuna dikkat edin. Aklınızda bulunsun.
Öneri: Müzik analizini kendi başınıza ele almak isterseniz, neredeyse 50.000 sanatçı için 50’den fazla özelliğe (ör. tempo, ses yüksekliği, dans edilebilirlik vb.) sahip The Million Song Dataset’e göz atabilirsiniz! Şarkı sözlerine müzikal özellikler eklemek oldukça kapsamlı bir analiz sağlar.
En Sık Kelimeler
Tam söz kümesinde en sık kullanılan kelimeleri basitçe değerlendirmek için, temizlenmiş ve filtrelenmiş veri setinizde count() ve top_n() kullanarak en üst n kelimeyi alabilirsiniz. Ardından, kelimeleri sayıya göre sıralamak için reorder() kullanın ve dplyr’ın mutate() fiiliyle sıralanmış değeri word’a yeniden atayın. Bu, ggplot()’un güzelce göstermesini sağlar.
prince_words_filtered %>% count(word, sort = TRUE) %>% top_n(10) %>% ungroup() %>% mutate(word = reorder(word, n)) %>% ggplot() + geom_col(aes(word, n), fill = my_colors[4]) + theme(legend.position = "none", plot.title = element_text(hjust = 0.5), panel.grid.major = element_blank()) + xlab("") + ylab("Şarkı Sayısı") + ggtitle("Prince Şarkı Sözlerinde En Sık Kullanılan Kelimeler") + coord_flip()Çoğu popüler müzikte olduğu gibi, love (aşk) yaygın bir tema gibi görünüyor. Sadece bu en üst kelimelere bakarak pek fazla varsayımda bulunmazdım; ancak sanatçının bakış açısına dair kesinlikle bazı içgörüler elde edebilirsiniz, yalnız tüm resmi vermez. Daha derine inmeden önce kısa bir görsel eğlence molası verin.
Kelime Bulutları
Kelime bulutları birçok çevrede kötü bir üne sahiptir ve dikkatli olmazsanız uygun olmayan bağlamlarda kullanılabilirler. Ancak doğası gereği hepimiz çok görsel varlıklarız ve gerçek içgörünün elde edilebileceği durumlar vardır. Sandy McKee’nin bazı örneklerine buradan bakın. Yalnız biraz ihtiyat payı ile kullanın.
Şimdilik, bazı havalı şeyler için wordcloud2 adlı yeni bir pakete göz atın. Bu paket, html widget’ları oluşturan yaratıcı bir bulut koleksiyonu sunar. Hatta bir kelimenin üzerine gelerek metindeki sıklığını görebilirsiniz. (Bu paket rMarkdown’da yavaş render edebilir ve sıklıkla kullandığı tarayıcı konusunda seçicidir. Umarız geliştirmeler yapılır.)
Daha da eğlenceli olması için biraz veri sanatı ekleyebilirsiniz…
wordcloud2(prince_words_counts[1:300, ], figPath = "guitar_icon.png", color = "random-dark", size = 1.5) letterCloud(prince_words_counts[1:300, ], word = "PRINCE", size = 2)Popüler Kelimeler
Şimdiye dek yalnızca tüm şarkılar boyunca en üst kelimeleri gördünüz. Peki bunları liste seviyesine göre ayırırsanız ne olur? Listelere giren şarkılarda bazı kelimeler, listeye girmeyen şarkılara göre daha mı yaygın? Bunlar toplum tarafından popüler görülen kelimelerdir.
Aşağıdaki kodda, her chart_level için ilk n kelimeyi almak üzere slice(seq_len(n)) kullanımına dikkat edin. Bu, top_n()’dan farklı çalışır ve grafiğinizde fasetleme kullanırken iyi bir seçimdir. (Böyle numaralar için her zaman farklı yollar olduğunu unutmayın.) Ayrıca, grafikte kelimeleri doğru sırada listeleyebilmek için row_number() işlevini kullanabilirsiniz. ggplot() varsayılan olarak kelimeleri alfabetik sıralar; grafikten önce sıralama yapmak iyi bir pratiktir.
popular_words <- prince_words_filtered %>% group_by(chart_level) %>% count(word, chart_level, sort = TRUE) %>% slice(seq_len(8)) %>% ungroup() %>% arrange(chart_level,n) %>% mutate(row = row_number()) popular_words %>% ggplot(aes(row, n, fill = chart_level)) + geom_col(show.legend = NULL) + labs(x = NULL, y = "Şarkı Sayısı") + ggtitle("Liste Seviyesine Göre Popüler Kelimeler") + theme_lyrics() + facet_wrap(~chart_level, scales = "free") + scale_x_continuous( # This handles replacement of row breaks = popular_words$row, # notice need to reuse data frame labels = popular_words$word) + coord_flip()Buradan ne tür içgörüler çıkarıyorsunuz?
Görüldüğü gibi, liste seviyeleri genelinde en üst kelimeler birbirine çok, ama çok benziyor. Bu, bir şarkının başarısını yalnızca sözlere bakarak tahmin etme umutlarımız için pek iyi görünmüyor! Ancak metin madenciliğiyle mümkün olanların yalnızca yüzeyine dokundunuz ve sonunda NLP ile öngörücü modellemeye geçeceksiniz.
Zamansız Kelimeler
Müzikte bazı kelimeler zamansız kabul edilir. Zamansız kelimeler zaman içinde kalıcılığını korur ve geniş bir kitleye hitap eder. Analizinizi on yıllara göre bölerseniz, bu kelimeler zirveye çıkar. Prince’in sözlerinden her on yıl için en üst kelimeleri almak ve hangi kelimelerin zamansız ya da trend olduğunu görmek için filtreleme, gruplama ve toplulaştırmayı kullanın. On yıla göre görüntülemek için facet_wrap() ile ggplot() kullanabilirsiniz.
timeless_words <- prince_words_filtered %>% filter(decade != 'NA') %>% group_by(decade) %>% count(word, decade, sort = TRUE) %>% slice(seq_len(8)) %>% ungroup() %>% arrange(decade,n) %>% mutate(row = row_number()) timeless_words %>% ggplot(aes(row, n, fill = decade)) + geom_col(show.legend = NULL) + labs(x = NULL, y = "Şarkı Sayısı") + ggtitle("Zamansız Kelimeler") + theme_lyrics() + facet_wrap(~decade, scales = "free", ncol = 5) + scale_x_continuous( # This handles replacement of row breaks = timeless_words$row, # notice need to reuse data frame labels = timeless_words$word) + coord_flip()Açıkça görülüyor ki love, time ve girl zamansız. Peki trend olan kelimeleri saptamak ne kadar kolay? truth milenyumun başında trend miydi? Belki de yalnızca bazı şarkılarda çok tekrarlanan bir kelimedir? Sıklık gerçekten temaları tanımlar mı? Bu, Birliğin Durumu konuşmalarını analiz etmek gibi diğer metin madenciliği görevlerinde olduğu gibi şarkı sözlerinde de işe yarar mı?
Kelime Uzunluğu
Kelime uzunluğu, söz yazarları için ilginç bir konudur. Kelime ne kadar uzunsa, kafiyelendirmek ve bir kalıba sığdırmak o kadar zordur. Aşağıda gösterilen kelime uzunlukları histogramı beklendiği gibidir; birkaç inanılmaz uzun istisna ile.
#unnest and remove undesirable words, but leave in stop and short words prince_word_lengths <- prince %>% unnest_tokens(word, lyrics) %>% group_by(song,decade) %>% distinct() %>% filter(!word %in% undesirable_words) %>% mutate(word_length = nchar(word)) prince_word_lengths %>% count(word_length, sort = TRUE) %>% ggplot(aes(word_length), binwidth = 10) + geom_histogram(aes(fill = ..count..), breaks = seq(1,25, by = 2), show.legend = FALSE) + xlab("Kelime Uzunluğu") + ylab("Kelime Sayısı") + ggtitle("Kelime Uzunluğu Dağılımı") + theme(plot.title = element_text(hjust = 0.5), panel.grid.minor = element_blank())Bu çılgınca uzun kelimeler neler? Tamamen eğlencelik bir kelime bulutu zamanı! Bu, kelime sıklığı yerine kelime uzunluğuna dayanır. Göz atın:
wc <- prince_word_lengths %>% ungroup() %>% select(word, word_length) %>% distinct() %>% arrange(desc(word_length)) wordcloud2(wc[1:300, ], size = .15, minSize = .0005, ellipticity = .3, rotateRatio = 1, fontWeight = "bold")Sözel Çeşitlilik
Bir metnin söz varlığı ne kadar çeşitliyse, sözel çeşitliliği (lexical diversity) o kadar yüksektir. Şarkı Söz Varlığı, bir şarkıda kullanılan benzersiz kelime sayısının bir temsilidir. Bu, yıllara göre şarkı başına ortalama benzersiz kelimelerin basit bir grafiğiyle gösterilebilir. Bu grafikte niceliksel içgörülere daha çok baktığınız için, orijinal veri setini yeniden token’layacak ancak tüm stop ve kısa kelimeleri tutacaksınız.
lex_diversity_per_year <- prince %>% filter(decade != "NA") %>% unnest_tokens(word, lyrics) %>% group_by(song,year) %>% summarise(lex_diversity = n_distinct(word)) %>% arrange(desc(lex_diversity)) diversity_plot <- lex_diversity_per_year %>% ggplot(aes(year, lex_diversity)) + geom_point(color = my_colors[3], alpha = .4, size = 4, position = "jitter") + stat_smooth(color = "black", se = FALSE, method = "lm") + geom_smooth(aes(x = year, y = lex_diversity), se = FALSE, color = "blue", lwd = 2) + ggtitle("Sözel Çeşitlilik") + xlab("") + ylab("") + scale_color_manual(values = my_colors) + theme_classic() + theme_lyrics() diversity_plotBu ne anlama geliyor? Son birkaç on yılda Prince’in söz çeşitliliğinde hafif bir yukarı yönlü eğilim vardı. Bu, liste başarısıyla nasıl ilişkilidir? Gerçekten söylemesi zor; ama karşılaştırma için yoğunluk ve liste geçmişini de çizelim.
Sözel Yoğunluk
Bu eğitim için sözel yoğunluğun, benzersiz kelime sayısının toplam kelime sayısına oranı olarak tanımlandığını hatırlayın. Bu, kelime tekrarının bir göstergesidir; bu da bir söz yazarının kritik bir aracıdır. Sözel yoğunluk arttıkça, tekrar azalır. (Not: bu, bir başka söz yazarlığı numarası olan ardışık tekrarı ima etmez.)
Prince’in yıllara göre sözel yoğunluğuna bir bakın. Yoğunluk için, stop kelimeler de dahil tüm kelimeleri tutmak en iyisidir. Bu nedenle, orijinal veri setiyle başlayıp kelimeleri unnest edin. Şarkı ve yıla göre gruplayın ve yoğunluğu hesaplamak için n_distinct() ve n() kullanın. Bunu geom_smooth() ile ggplot()’a aktarın. Doğrusal bir yumuşatma modeli için method="lm" ile ek bir stat_smooth() ekleyin.
lex_density_per_year <- prince %>% filter(decade != "NA") %>% unnest_tokens(word, lyrics) %>% group_by(song,year) %>% summarise(lex_density = n_distinct(word)/n()) %>% arrange(desc(lex_density)) density_plot <- lex_density_per_year %>% ggplot(aes(year, lex_density)) + geom_point(color = my_colors[4], alpha = .4, size = 4, position = "jitter") + stat_smooth(color = "black", se = FALSE, method = "lm") + geom_smooth(aes(x = year, y = lex_density), se = FALSE, color = "blue", lwd = 2) + ggtitle("Sözel Yoğunluk") + xlab("") + ylab("") + scale_color_manual(values = my_colors) + theme_classic() + theme_lyrics() density_plotEğilimleri karşılaştırmak için, liste geçmişi (yani listelere giren başarılı şarkılar) için bir grafik oluşturun ve bunu çeşitlilik ve yoğunlukla kıyaslayın. gridExtra’dan grid.arrange() kullanarak yan yana çizin.
chart_history <- prince %>% filter(peak > 0) %>% group_by(year, chart_level) %>% summarise(number_of_songs = n()) %>% ggplot(aes(year, number_of_songs)) + geom_point(color = my_colors[5], alpha = .4, size = 4, position = "jitter") + geom_smooth(aes(x = year, y = number_of_songs), se = FALSE, method = "lm", color = "black" ) + geom_smooth(aes(x = year, y = number_of_songs), se = FALSE, color = "blue", lwd = 2) + ggtitle("Liste Geçmişi") + xlab("") + ylab("") + scale_color_manual(values = my_colors) + theme_classic() + theme_lyrics() grid.arrange(diversity_plot, density_plot, chart_history, ncol = 3)Yukarıdan, Prince’in sözel çeşitliliği ve yoğunluğunda yıllar içinde hafif bir artış olduğunu görüyorsunuz. Bu eğilim, tüm popüler müzikle nasıl karşılaştırılır? Bir çalışma, Hit Şarkılarda sözel yoğunluğun azaldığını, bunun da tekrarın arttığını (yani "daha az şey söyleyen daha çok kelime") gösterdiğini ortaya koyuyor. Prince’in şarkılarında olan bu değil. Bir diğer çalışma ise tüm popüler müzik genelinde çeşitliliğin (benzersiz kelimeler) zamanla arttığını ve bunun Prince’in müziğiyle olumlu yönde ilişkili olduğunu ortaya koyuyor. Bu, tarih boyunca liste sıralamalarında tür çeşitliliğinin artmasıyla ilişkili olabilir. Tür, bu veri setinde bulunmayan kritik bir veri parçası. Popüler müzik için liste geçmişi düşerken R&B/Rap için artıyor olabilir mi?
Öneri: Bu sonuçları düşünmenizi ve hatta bu becerileri kendi başınıza kullanabileceğiniz farklı veri setleri aramanızı teşvik ediyorum! Unutmayın, korelasyon nedenselliği ima etmez.
TF-IDF
Şimdiye kadar kullandığınız yöntem, tüm veri setine baktı; ancak bir bütün içinde çeşitli terimlerin bir belge için ne kadar önemli olduğunu sayısallaştırmayı ele almadı. Terim sıklığına baktınız ve stop kelimeleri kaldırdınız; ama bu en sofistike yaklaşım olmayabilir.
Karşınızda TF-IDF. TF "terim sıklığıdır" (term frequency). IDF ise "ters belge sıklığıdır" (inverse document frequency) ve yaygın kullanılan kelimelere daha düşük, koleksiyonda az kullanılan kelimelere daha yüksek ağırlık verir. TF ve IDF’yi birleştirdiğinizde, bir terimin önemi, ne kadar nadir kullanıldığına göre ayarlanır. TF-IDF’nin ardındaki varsayım, bir belgede daha sık görünen terimlerin daha yüksek ağırlık alması gerektiğidir; ta ki pek çok belgede de görünmüyorsa. Formül özetle şöyle verilebilir:
Dolayısıyla, bir koleksiyondaki belgelerin daha azında görülen kelimeler için herhangi bir terimin IDF’si daha yüksek bir sayıdır. tidytext’in sağladığı bind_tf_idf() işleviyle, liste seviyesi başına en önemli kelimeleri incelemek için bu yeni yaklaşımı kullanabilirsiniz. Bu işlev, TF ve IDF’yi hesaplar ve TF*IDF çarpımıyla birlikte bağlar. Girdi olarak, belge (şarkı) başına token (kelime) başına bir satır içeren tidy bir metin veri seti alır. Sonuçları yeni sütunlarda göreceksiniz.
Öyleyse, orijinal Prince veri çerçevenizi alın ve token’ları kelimelere açın, istenmeyen kelimeleri kaldırın; ancak stop kelimeleri tutun. Sonra bind_tf_idf() kullanarak formülleri çalıştırın ve yeni sütunlar oluşturun.
Şimdi, çok yaygın kelimeler için IDF ve TF-IDF’nin 0 olduğunu görebilirsiniz. (Teknik olarak, IDF terimi doğal logaritmada 1 olur ve bu nedenle bu kelimeler için sıfırdır.) Yukarıdaki sonuçlarınızı arrange() içine aktarın ve tf-idf’ye göre azalan şekilde sıralayın. Birkaç adım daha ekleyin ve Prince’in sözlerindeki kelimelere bakmanın farklı bir yolunu göreceksiniz.
top_popular_tfidf_words <- popular_tfidf_words %>% arrange(desc(tf_idf)) %>% mutate(word = factor(word, levels = rev(unique(word)))) %>% group_by(chart_level) %> slice(seq_len(8)) %>% ungroup() %>% arrange(chart_level, tf_idf) %>% mutate(row = row_number()) top_popular_tfidf_words %>% ggplot(aes(x = row, tf_idf, fill = chart_level)) + geom_col(show.legend = NULL) + labs(x = NULL, y = "TF-IDF") + ggtitle("Liste Seviyesine Göre TF-IDF ile Önemli Kelimeler") + theme_lyrics() + facet_wrap(~chart_level, ncol = 3, scales = "free") + scale_x_continuous( # This handles replacement of row breaks = top_popular_tfidf_words$row, # notice need to reuse data frame labels = top_popular_tfidf_words$word) + coord_flip()Vay canına, TF-IDF kullanmak potansiyel olarak önemli kelimelere bambaşka bir bakış açısı sunuyor. Elbette yorum tamamen öznel. Herhangi bir desen fark ettiniz mi?
Şimdi de TF-IDF’ye zamana göre bakın:
tfidf_words_decade <- prince %>% unnest_tokens(word, lyrics) %>% distinct() %>% filter(!word %in% undesirable_words & decade != 'NA') %>% filter(nchar(word) > 3) %>% count(decade, word, sort = TRUE) %>% ungroup() %>% bind_tf_idf(word, decade, n) %>% arrange(desc(tf_idf)) top_tfidf_words_decade <- tfidf_words_decade %>% group_by(decade) %>% slice(seq_len(8)) %>% ungroup() %>% arrange(decade, tf_idf) %>% mutate(row = row_number()) top_tfidf_words_decade %>% ggplot(aes(x = row, tf_idf, fill = decade)) + geom_col(show.legend = NULL) + labs(x = NULL, y = "TF-IDF") + ggtitle("On Yıla Göre TF-IDF ile Önemli Kelimeler") + theme_lyrics() + facet_wrap(~decade, ncol = 3, nrow = 2, scales = "free") + scale_x_continuous( # this handles replacement of row breaks = top_tfidf_words_decade$row, # notice need to reuse data frame labels = top_tfidf_words_decade$word) + coord_flip()Şimdi kesinlikle daha derin bir içgörü düzeyi elde ediyorsunuz. Zamansız kelimeler artık baskın değil. Konular veya temalar belirmeye başladı mı? Gerçekten yalnızca grup başına birkaç kelimeyle mümkün mü? Bunu ikinci eğitimde (İkinci Bölüm: NLP ile Duygu Analizi ve Konu Modellemesi) yeni boyutlara taşıyacaksınız.
Bu yöntemle hızlı bir kelime bulutu, Prince’in sözlerindeki önemli kelimelere yeni bir bakış sunar ve biraz daha ilgi çekicidir…
wc <- tfidf_words_decade %>% arrange(desc(tf_idf)) %>% select(word, tf_idf) wordcloud2(wc[1:300, ], color = "random-dark", minRotation = -pi / 6, maxRotation = -pi / 3, minSize = .002, ellipticity = .3, rotateRatio = 1, size = .2, fontWeight = "bold", gridSize = 1.5 )Sonuç
Bu vaka çalışmasında önce, yalnızca temel unsurlara bakarak gerçek veriye bir göz attınız. Veri temizleme ve bilgilendirici olmayan kelimeleri kaldırma gibi bazı koşullandırmalar yaptıktan sonra, şarkı düzeyinde keşifsel bir analize başladınız.
Ardından, sözleri token’lanmış kelimelere ayırarak sözel karmaşıklığa bakabilmek için metin madenciliğine daha derinlemesine girdiniz. Sonuçlar, bir sonraki adımlar olan duygu analizi ve konu modellemesi için kritik içgörüler sağlar.
Son olarak, bir belgede bir kelimenin, ilgi duyulan bir sonuçla ilişkili bilgisini temsil etmek için TF-IDF analizini kullandınız. Bunun müzikte temaları belirlemenin iyi bir yolu olduğunu düşünebilirsiniz; ama hikâyenin yalnızca yarısına sahipsiniz. İkinci Bölüm, Gizli Dirichlet Ayrımı (LDA) adlı gözetimsiz bir öğrenme yöntemini ele alır. Veri Bilimi’nin her alanında olduğu gibi, içgörü kazanmak için seçebileceğiniz pek çok yöntem vardır. Bu vaka çalışmasının İkinci ve Üçüncü Bölümlerinde bu seçeneklerden daha fazlasını ele alacaksınız.
Umarım, keşifsel analizden duygu analizine, konu modellemesine ve öngörücü içgörülere uzanan bu yolculuğa benim kadar siz de heyecanlısınızdır.
Okuduğunuz için teşekkürler; bir sonraki eğitimde görüşmek üzere!