大家好,本文志在發表一篇文本挖掘+蘇打綠歌詞 的文章,意義如下:

  1. 有完整的文本預處理、分詞、主題探究等文本挖掘流程和代碼,可供參考借鑒。
  2. 數據集是蘇打綠自出道以來的歌詞,探究了新詞、主題、創作可能。
  3. 適合追星族自己上手操作,不論分析歌手的歌詞、演員的台詞等等,都能有所啟發。
  4. 適合幫助數據分析新人找到有意思的課題進行思路開拓和研究~

先來一張資深打粉證明- -

聲明:這篇文章純粹出於我對於蘇打綠無可比擬的喜愛與珍惜,所以在學習文本挖掘這門課程的時候不由自主選擇了用他們的歌詞作為研究對象。希望我能從自己的角度,完成文本挖掘+歌詞探究的Idea,以此更加深入的了解我所熱愛的這個團體,也能夠幫助更多的人了解和喜歡上他們。


許多人評價說,華語樂壇已經趨向衰敗,沒有80,90年代的輝煌。在中國大陸,流行音樂中存在缺乏原創力、法律不健全、盜版猖獗、音樂格調低俗等現象。音樂的價值取向也逐漸趨向商業化,以追求利益為目標而缺乏了藝術價值。但中國樂壇現在仍有許多優秀的作品未被深入了解探究,以歌詞中蘊含著美感與樂趣,使音樂更有獨特的中華文化魅力。

以作詞聞名的不僅有香港著名作詞人林夕(創作量達4000,為王菲、陳奕迅等歌王歌后都作過詞)、方文山(周杰倫的御用詞人)、黃偉文(香港著名填詞人)等,更有獨立樂團蘇打綠主唱吳青峰,畢業於台灣政治大學中文系,曾獲台灣金曲獎「最佳作詞人獎」。

知名樂團蘇打綠2001年成立於校園,2003年確立6人陣容,2004年5月,蘇打綠正式出道,發行第一張單曲《空氣中的視聽與幻覺》。2005年,蘇打綠髮行了《SodaGreen》。2006年,蘇打綠髮行專輯《小宇宙》。2012年,蘇打綠獲得第21屆金曲獎最佳樂團獎。2013年,蘇打綠髮行專輯《秋:故事》,該專輯成為2013年度iTunes Store最受歡迎專輯。2014年,蘇打綠開始了十周年世界巡迴演唱會。2016年蘇打綠獲得第27屆台灣金曲獎最佳國語專輯獎、最佳樂團獎、最佳編曲人獎、最佳作詞人獎和最佳專輯製作人獎。

本文中,作者從文本(數據)挖掘的角度去「探索」蘇打綠樂團的作品,挑戰不同場景下(現代漢語和歌詞文本)文本處理和分析的異同點,結合數據之美和詩歌之雅,用跨界思維去發現一些有趣的東西。

本文的語料是台灣樂壇蘇打綠自出道以來的94首歌詞,基本涵蓋從<空氣中的視聽與幻覺>到<冬 未了>中的所有歌曲,約38735個字元

文本挖掘的經典流程是:獲取文本——文本預處理——分詞、去停用詞——建模。在本文中,在這個過程中,作者意識到,歌詞文本有其特殊性,如果直接進行分詞,可能會造成分詞的不準確,進而影響下一步的研究,因此在分詞之前加入基於互信息和左右熵的新詞發現的環節;接下來以蘇打綠髮行的四季專輯(韋瓦第計劃)為研究對象,探究歌詞的主題變化;最後基於GRU神經網路進行歌詞生成,完成歌詞的處理、挖掘、創作,三大部分。

本文研究框架

發現新詞

—— 歌詞有什麼好研究的?

歌詞文本作為一類特殊的文本,有其獨特的藝術性和價值。通常來講,在使用python進行文本分詞的時候,會使用jieba分詞模塊。使用現有分詞模塊會面對的問題是,如果一些辭彙不在其中,會造成分詞不準確的現象。

那麼,發現新詞的規則可以如何制定呢?本文主要從互信息左右熵兩個概念入手,制定新詞發現的規則。

  • 互信息

——成詞的標準之一:內部凝固程度

互信息的定義為:

I(x,y)=log(p(x,y)/p(x)p(y))

什麼是凝固程度?比如說一個詞「電影院」,如果「電影」和「院」真的是各自獨立地在文本隨機出現,那麼他兩正好出現在一起的概率會很小。我們通過計算P(電影)×P(院)遠小於P(電影院),這時候我們就會發現「電影院」很有可能是一個有意義的詞。因此我們枚舉文本片段的組合方式,然後設置凝聚程度的最小值。

  • 左右熵

——成詞的標準之二:自由運用程度

左右熵的定義為:(以左熵為例)

E_{L}(W)=-sum_{forall a}{P(aW)log_{2}(P(aW|W))}

什麼是自由運用程度?比如說一個詞「輩子」, 用法非常固定,除了「一輩子」、「這輩子」、「上輩子」、「下輩子」,基 本上「輩子」前面不能加別的字了。以至於直覺上會覺得「輩子」不能單獨成詞。因此我們說能夠自由運用是一個詞的關鍵。

我們這裡使用左右熵來衡量主要是想表示預選詞的自由程度,左右熵越大,表示這個詞的左邊右邊的詞換的越多,那麼它就很有可能是一個單獨的詞。得具有豐富的左鄰詞集合與右鄰詞集合。

先介紹信息熵的概念,信息熵能夠反映一個事件的結果平均會給你帶來多大的信息量。如果某個結果的發生概率為p,當你知道它確實發生了,那麼你得到的信息量為-log(p)。 如果一顆骰子的六面是1,1,1,2,2,3。那麼我們投到1時,得到的信息量是-log(1/2);投到2時,得到的信息量是-log(1/3);投到3時得到的信息量是-log(1/6)。事情越不確定,信息熵越大。

我們使用信息熵來衡量一個文本片段的左鄰字集合與右鄰字集合有多隨機。

凝固程度與自由程度缺一不可,只看凝固程度的話容易找到半個詞,只看自由度的話容易得到無意義的垃圾片語。

接下來進入新詞發現的流程:

流程:

  1. 輸入: 按行分割的未切詞文本
  2. 文檔清洗, 去除非中文字元
  3. 構建子串-頻率字典, 計算長度從1到max_word_length的所有子串的頻率
  4. 構建新詞候選集, 計算所有子串-頻率字典中的子串的PMI值,PMI大於min_pmi的所有子串構成新詞候選集
  5. 生成合法新詞, 計算新詞候選集中的所有子串左右鄰居信息熵,信息熵高於min_entropy的所有子串構成最終的新詞集
  6. 輸出:新詞集

## 正則表達式清洗文本模塊 ##

import codecs
import re

filepath = E:/研究生課程/文本挖掘/final project/sodagreen_lyrics.txt
key = [u演唱,u單曲,u專輯,u蘇打綠,u,u,u編曲,u史俊威,u蘇打綠,u作詞,u作曲,u演唱]
new = []
with open(rE:/研究生課程/文本挖掘/final project/sodagreen_lyrics.txt,r,encoding=utf-8) as f:
content = f.readlines()
for line in content:
if True:
line = re.sub(r"[s+.!/_,$%^*(+"]+|[+——!,。??、~@#¥%……&*()+]+", "", line)
line = re.sub(r[0-9a-zA-Z-|」「*-|《》)]+, , line)
line.strip()
if len(line) != 0 and all(i not in line for i in key):
new.append(line+ )
with codecs.open(E:/研究生課程/文本挖掘/final project/mypart/new.txt,w) as f:
for x in new:
f.write(x)

##看看生成文本啥樣##

文本預處理前
文本預處理後

##基於清洗的文本進行新詞發現##

def read_txt(filepath):
dataset=[]
for line in open(filepath,r,encoding=utf-8):
line = re.sub(r[0-9a-zA-Z], , line)
dataset.append(line)
return dataset
raw_sentences = read_txt(E:/研究生課程/文本挖掘/final project/mypart/new.txt)
text = .join(raw_sentences).replace(
,"")
stop_word=[,,),(,,,,,,
,,, ,-,,,.,,[,],,/,.,",u3000,,,,,,?]

for i in stop_word:
text=text.replace(i,"")

min_entropy=0.8
min_p=4
max_gram=4
count_appear=3

def gram(text,max_gram):
t1=[i for i in text]
loop=len(t1)+1-max_gram
t=[]
for i in range(loop):
t.append(text[i:i+max_gram])
if max_gram==1:
return t1
else:
return t
import math
def pro(word):
len_word=len(word)
total_count=len(word_all[len_word])
pro=freq_all[len_word][word]/total_count
return pro
def entropy(alist):
f=FreqDist(alist)
ent=(-1)*sum([i/len(alist)*math.log(i/len(alist)) for i in f.values()])
return ent

freq_all=[0]
word_all=[0]
for i in range(1,max_gram+1):
t=gram(text,i)
freq=FreqDist(t)
word_all.append(t)
freq_all.append(freq)

#篩選一部分符合互信息的單詞
final_word=[]
for i in range(2,max_gram+1):
for j in word_all[i]:
if freq_all[i][j]<count_appear:
pass
else:
p=min([pro(j[:i])*pro(j[i:]) for i in range(1,len(j))])
if math.log(pro(j)/p)>min_p:
final_word.append(j)
final_word=list(set(final_word))

##新詞發現展示##

中間是發現的新詞,挑出幾首作為示例,每首歌里 上面是jieba分詞結果,下面是基於新詞發現的分詞結果。可以看到,「控制狂"這個詞就被發現啦~~~還有"再遇見","背著你」等等~

哈哈哈開心。

新詞發現展示

主題解讀

——蘇打綠在唱什麼? 韋瓦第計划了解一下~

韋瓦第計劃(Project Vivaldi),由台灣知名樂團蘇打綠髮起,靈感來源於以音樂呈現文字、寫出了四季小提琴協奏曲的18世紀初古協奏曲之父-安東尼奧·維瓦爾第。蘇打綠以「One Season, One Concept」,四個季節,四座城市,用四種情緒製作四張專輯,發動跨國「音」謀,打造完全「蘇打綠」的曲風。

主題分析,在這裡用了TextRank的方法:

TextRank 演算法是一種用於文本的基於圖的排序演算法。其基本思想來源於谷歌的 PageRank演算法, 通過把文本分割成若干組成單元(單詞、句子)並建立圖模型, 利用投票機制對文本中的重要成分進行排序, 僅利用單篇文檔本身的信息即可實現關鍵詞提取、文摘。和 LDA、HMM 等模型不同, TextRank不需要事先對多篇文檔進行學習訓練, 因其簡潔有效而得到廣泛應用。

流程:

  1. 分詞、去停用詞得到候選關鍵詞
  2. 構建候選關鍵詞圖
  3. 根據公式,迭代傳播各節點的權重,直至收斂
  4. 對節點權重進行倒序排序,從而得到最重要的T個單詞,作為候選關鍵詞

去除停用詞並且統計TOPK詞頻和主題
def final_words(stop_word_filepath,seg_list,k):
stop_words= read_txt(stop_word_filepath)
new_stop_words=[]
for i in stop_words:
i = i.replace(
,"")
new_stop_words.append(i)
new_stop_words.append( )
new_seg_list=[]
for word in seg_list:
if word!=
:
if word not in new_stop_words:
new_seg_list.append(word)
data = dict(Counter(new_seg_list))
data2 = sorted(data.items(), key=lambda x: x[1], reverse=True)
tfidf= analyse.extract_tags("".join(new_seg_list), topK=k, withWeight=False, allowPOS=())
textrank=analyse.textrank("".join(new_seg_list), topK=k, withWeight=False, allowPOS=(ns, n, vn, v))
return new_seg_list,data2[:k],tfidf,textrank

利用TextRank模型對四季專輯進行主題挖掘,可以得到如下的主題挖掘結果:

春:時間,回家,生命,夢境,天空,逝去,保留,尋找,煙火,盛開,期待,燃燒,遊戲,美麗,顏色,迎接,停手,合奏,肩膀,日光

夏:魔鬼,慶祝,歇斯底里,幻想,背叛,地點,長大,愛情,倒退,追求,胸膛,世界,弄污,擁有,英雄,生活,走過,森林,下班,地獄

秋:時間,天地,世界,海洋,答答,天使,大地,改變,情緒,天空,傷口,謊言,故事,不見,人生,生命,翅膀,幻象,嬰兒,狩獵

冬:慾望,星辰,投訴,世界,陪伴,感覺,細菌,輪迴,有沒有,帶來,情緒,藝術,能源,否定,有罪,活著,滅絕,理睬,生恨,交給

生成詞雲圖為:

台東春天的溫暖民謠——《春.日光》

春.日光 主題詞雲圖

倫敦夏天的熱情搖滾——《夏/狂熱》

夏/狂熱 主題詞雲圖

北京秋天的憂傷詩歌——《秋:故事》

秋:故事 主題詞雲圖

柏林冬天的莊嚴古典——《冬 未了》

冬 未了 主題詞雲圖

蘇打綠韋瓦第計劃,就是每張主題都這麼明晰又吸引人啊- - 。春夏秋冬,每個季節都被你們包裹圍繞了。

AI創作

—— 你能寫歌嗎?我不能。但AI可以。

生成歌詞的項目還是有一些。網上大家可以搜索看看,有汪峰、周杰倫等等的歌詞生成項目。

通常來講,RNN是比較基礎的文本生成神經網路。但是傳統的RNN在訓練long-term dependencies 的時候會遇到很多困難,最常見的便是vanish gradient problen(梯度消失)。在這個基礎上,大牛們設計了更加精密的recurrent unit,如LSTM,GRU。LSTM和GRU都能通過各種Gate將重要特徵保留,保證其在long-term 傳播的時候也不會被丟失;還有一個不太好理解的作用就是有利於BP的時候不容易vanishing。

LSTM的重複網路模塊的結構很複雜,它實現了三個門計算,即遺忘門、輸入門和輸出門;GRU保持了LSTM的效果同時又使結構更加簡單。

在探索過程中,我們採取了兩種訓練策略進行訓練:

首先是整首訓練:給每個歌詞 兩個標識符作為開頭和結尾,將每首歌詞獨立作為樣本放入模型進行訓練。整首訓練的弊端是歌詞序列長度較大,模型訓練時會弱化遠端信息;數據量較少,訓練效果不好;無法控制輸出歌詞長度。

接下來我們採取了句訓練:將歌詞數據集每句拆分成一行,作為整體進行訓練。訓練時隨機採樣某一定長度的句組構成batch。句訓練的優點是可以生成指定長度的歌詞;可以自定義歌詞的生成輸入(歌詞開頭)。

在訓練過程中,我們採用adam優化器,設置起始學習率為0.001,用交叉熵損失函數做反向傳播。對於純歌詞樣本數據,我們發現在訓練了10000個epoches後,模型的過擬合程度較高,生成的歌詞文本有較多和原文重複。故取節點10000作為截取保存點。同樣的,對於歌詞+詩樣本數據,我們訓練了40000個epoches。

GRU生成蘇打綠風格歌詞

然後——由於作者是較為資深的蘇打綠歌迷——所以我知道老吳很喜歡夏宇的詩啊——不信你們看看——

所以我不由得想到,假如把夏宇的詩詞也加入訓練,是不是會有更神奇的效果~

GRU生成蘇打綠+夏宇風格歌詞

啊總之這個歌詞肯定是不能直接拿來用,但是自己看看,然後修改修改,還是很好用的~


最後我送上一個Bonus~(對於打粉來說可能不是,嘻嘻,是公開的秘密~)

就,吳青峰就是詩人啊。

這是秋專輯裡的所有歌的歌名。

這是每首歌的最後一句:

大家把最後一個字連起來,讀一讀?

致敬蘇打綠,我永遠愛你們呀。

最後@飛奔的鹹魚,我的隊友,嘻嘻。

參考:

  1. 新詞發現

新詞發現 - sinat_33731745的博客 - CSDN博客?

blog.csdn.net

2. GRU神經網路

深度學習:循環神經網路(RNN)的變體LSTM、GRU - std=c++11 - CSDN博客?

blog.csdn.net
圖標

推薦閱讀:
相关文章