以 jieba 與 gensim 探索文本主題:五月天人生無限公司歌詞分析 ( I )

Youngmi huang
PyLadies Taiwan
Published in
12 min readNov 13, 2017

構成語句最基本為字詞,使用 word2vec 將字詞轉為詞向量後,為了從文本數據得到顯著而有用的資訊,需要的是探索支援自然語言處理的工具與嘗試,例如基於 python 的主題模型函式庫 gensim ,是 python 做自然語言處理必備的工具之一。

本次主題著重於實現心目中想做的數據集的運用,會拆成上下篇,上篇主要為 jieba 的中文斷詞與特徵萃取;下篇則會聚焦於 gensim 主題建模的使用。

源起

五月天在 2017 年底的「人生無限公司演唱會」,在 10 月開搶後秒殺,短短15 分鐘完售 24 萬張門票,為什麼大家這麼喜歡搶五月天的門票?曾經有人說:每個人心目中都有一首五月天,我將它解讀為,每個人腦海中「第一首浮現的五月天」,那一首歌,陪伴人們成長過程的青春、夢想與回憶等。

本次僅以「歌詞」作為相近歌單之間的主題探索,歌詞為文本,是屬於自然語言處理領域,若要做到更精細,可以結合文本+語音的方式去找尋歌曲相似度,此任務就會較為複雜。

為什麼要做這件事? 怎麼應用?

出於好奇「人生無限公司演唱會」歌單裡的歌詞有哪些關鍵字詞,掌握這些字詞之後,在和五月天以及全場聽眾一起唱歌的時候,就可以避免不會唱的窘境( e.g. 派對動物的關鍵字詞: oh oh oh oh) 。

另外,演唱會進行中,我們並不知道會有什麼驚喜,也許唱了一首冷門歌曲而你很喜歡,記下歌名之後,就可以透過主題建模找尋相近歌詞的方式,找到另一首你可能也很喜歡的歌曲。

歌詞數據集

蒐集了在 2017/9 ~ 2017/10 之間,五月天人生無限公司巡迴演唱會的歌單(於深圳、洛陽、南京、福州這 4 場),共 33 首歌詞 (取自:Moji 魔鏡歌詞網)。

數據集選取是保有彈性的,每個人可自由選擇喜歡的歌詞做資料蒐集 ( e.g. 蘇打綠、周杰倫、玖壹壹)。但在資料前處理的時候會需要一點時間(包含: 資料格式、特殊字元、統一英文大小寫、以及歌詞雜訊等),這次花了不少時間在這塊以及嘗試讀取資料(這又是另一段故事了),建議將資料整理成下列格式:

同一首歌詞之間是空白、不同首歌詞之間是換行、存成文字檔 (預設編碼是 utf-8 )

任務說明

因 python3 對於中文支持與編碼更友善,本篇以 python3 進行。所需安裝套件:jiebagensimwordcloud (文字雲)。

  • 歌詞分析:較為初級的任務,利用 jieba.analyse取出文章中的關鍵詞,透過文字雲做視覺化呈現 。
  • 主題建模:引用 gensim 當中 corporamodelssimilarities 模組,分別做語料庫建立、主題模型、與相似度比較。

歌詞分析

歌詞分析主要用到的是 jieba.analyse.extract_tags,背後的原理為 tf-idf 算法。

1. tf - idf 簡介 ( term frequency–inverse document frequency )

tf - idf 是一種統計方法,此原理為評估一個字詞對於一個檔案集,或一個語料庫中的其中一份檔案的重要程度,這個概念十分重要。

  • tf (term frequency ):詞頻,計算該詞語在文章所出現的次數
  • idf ( inverse document frequency ):逆文檔頻率,衡量該字詞的重要性
Text Clustering : Get quick insights from Unstructured Data

字詞的重要性隨著它在檔案中出現的次數成正比增加,但同時會隨著它在語料庫中出現的頻率成反比下降。也就是說,當 tf 值很高,而 df 值很低,這時得到的權重值就能夠把常見的關鍵字濾掉。詳細數學原理可參考維基百科

以「乾杯」這首歌詞簡單舉例:

五月天乾杯歌詞
# import jieba 並使用繁中字典
import jieba.analyse
jieba.set_dictionary("jieba_dict/dict.txt.big")
# 將乾杯這首歌的關鍵字詞取出來
# topK代表要取的關鍵字次數
with open("lyrics/single_song.txt", "rb") as f:
for line in f:
tags = jieba.analyse.extract_tags(line,
topK=10,
withWeight=True)
for tag, weight in tags:
print(tag + "," + str(int(weight * 10000)))
# Result
不會,3290
時間,2741
歲月,2741
回憶,2741
一天,2715
也許,2193
終點,2193
舉起,2193
懷念,2193
悠悠的,2169

2. 從歌詞萃取重要關鍵字

接下來將演唱會歌單出現的 33 首歌詞同樣以 jieba.analyse.extract_tags取出歌曲的 10 大關鍵字,透過萃取出來的資訊,其實不難猜出下面這 5 首歌的歌名(你的腦海裡應該開始出現著這首歌的旋律了)。

# 把每首歌的tags取出
with open("lyrics/test1.txt", "rb") as f:
for line in f:
tags = jieba.analyse.extract_tags(line,10)
print(",".join(tags))
# Result (因篇幅有限、這裡僅列前5項)不會,時間,歲月,回憶,一天,也許,終點,舉起,懷念,悠悠的

我們,哪裡,從不,相識,那個,場景,出現,不曾,相遇,每秒

我們,好好,一隻,不過,沒有,變老,時間,喧囂,最後,知道

後來,我們,人生,無論是,淚水,一個,期待,中能,然後,回憶

滾燙,入陣曲,無悔,夜未央,天未亮,倖存,沙場,臉龐,淚未,心未涼

上述是看個別歌曲的關鍵字;接著我們來看這次五月天在「人生無限公司巡迴演唱會」所唱的歌單裡的含有哪些元素:

# 將每首歌的前10個tags存檔
import codecs
wtags = codecs.open("lyrics/lyrics_tags.txt", "w","utf-8")
with open("lyrics/test1.txt", "r") as f1:
for line in f1:
words = jieba.analyse.extract_tags(line,10)
wtags.write(" ".join(words))
f1.close()

# 把所有歌的前10個tags變為萃取資料的input
with open("lyrics/lyrics_tags.txt", "rb") as f2:
for line in f2:
tags = jieba.analyse.extract_tags(line,15)
print(",".join(tags))
f2.close()
# Result
我們,回憶,沒有,一個,快樂,孤單,什麼,改變,人生,時間,歲月,終點,那個,出現,一隻

3. 使用 wordcloud 呈現

wordcloud 這個套件是文字雲,預設是支援英文(因為是 amueller 這位作者開發的),需另外下載中文字體,才能在文字雲當中顯現中文,若是英文歌詞則無需特別下載字體。可參考 Google Noto Fonts 開源字體下載,選擇支援中文的字型。

import numpy as np
import matplotlib.pyplot as plt
from wordcloud import WordCloud
# 讀取每首歌的前10個tags
text = open("lyrics/lyrics_tags.txt").read()
# 設定停用字(排除常用詞、無法代表特殊意義的字詞)
stopwords = {}.fromkeys(["沒有","一個","什麼","那個"])
# 產生文字雲
wc = WordCloud(font_path="NotoSerifCJKtc-Black.otf", #設置字體
background_color="white", #背景顏色
max_words = 2000 , #文字雲顯示最大詞數
stopwords=stopwords) #停用字詞
wc.generate(text)# 視覺化呈現
plt.imshow(wc)
plt.axis("off")
plt.figure(figsize=(10,6), dpi = 100)
plt.show()
左圖為引用支援中文字體,可正常呈現中文;右圖未設定中文字體,僅能呈現英文

4. 小結

透過「從歌詞文本當中找出關鍵字 +文字雲視覺化」的關鍵字歌詞呈現,我們從五月天這 4 場「人生無限公司巡迴演唱會」共 33 首歌曲當中看到的結果:以「我們」、「人生」、「回憶」、「快樂」為主軸,以下分為 4 種不同處理程度的歌詞檔案,所呈現的結果探討如下:

數據信息量:黃色面積越大代表所含資料量越大、同時訊息也越雜亂;越往右邊代表過程中對資料進行處理的程度大小差異;資料量越大不一定就是完全不好,同理文本訊息精煉度也不一定是越極右端就越好,有可能精煉到失去某些重要特徵,會需要時間嘗試。而這個探索的過程,對後續建模時的特徵選取、停用字建立( stoplist ),都會有所幫助。

補充:文字雲呈現四種不同處理程度的資料

文字雲本身呈現的是詞頻結果( term fequency ),尚未衡量逆文檔頻率( inverse document frequency ),故以下針對資料處理程度的不同進行討論:

  1. 讀取原歌詞檔案(未斷詞)

直接將 33 首歌詞丟入,因為每一首歌尚未進行斷詞,故對文字雲來說,歌詞中出現中文是讀取長語句,反而像是出現英文歌詞( e.g. oh oh ) 是單詞,跟中文語句相比等於是斷好詞了,也更容易計算次數。

# 讀取中文歌詞
會不會 有一天 時間真的能倒退 退回 你的我的 回不去的 悠悠的歲月 也許會 有一天 世界真的有終點 也要和你舉起回憶釀的甜 和你再乾一杯
# 讀取英文歌詞
let's go party party all night oh oh oh oh
hey lonely lonely goodbye oh oh oh oh

「oh oh」在派對動物出現 30次、傷心的人別聽慢歌出現 4 次;「yeah yeah」在黑暗騎士當中就出現了 17 次。

2. 讀取原歌詞檔案(有斷詞)

經過斷詞後,對文字雲來說就是計算較短的字詞,例如,乾杯當中的一段,是計算「會」、「不會」、「有」、「一天」、「時間」、「真的」、「能」、「倒退」的出現數量。

# 未斷詞
「會不會 有一天 時間真的能倒退」
# 有斷詞
「會 不會 有 一天 時間 真的 能 倒退」

3. 讀取每首歌的前 10 大關鍵字

加入衡量關鍵字的處理資料,使用前半部使用 jieba.analyse.extract_tags獲得 33 首歌各別的 10 大 關鍵字(共 330 個關鍵字),此為精煉後的訊息,為本次所採用之範例。

4. 讀取最終關鍵字:代表整體 33 首歌的 200 大關鍵字

將上述獲得的 330 個關鍵字,當作 input,一樣再做一次 jieba.analyse.extract_tags獲得,取重要性前 200 個關鍵字;與上述相比,關鍵字從 330 個精鍊成 200 個,前五大趨勢出現的「我們」、「回憶」、「快樂」、「改變」、「孤單」,這些在歌詞裡出現的字詞都是構成「人生」更細的顆粒元素呢。

下集會接續著「主題建模」的介紹,聚焦在使用 gensim ,同樣是「人生無限公司」有出現的歌曲,透過歌詞文本的相似度計算出不同主題下各字詞的比率,進而找出相似歌詞的應用。

本次完整程式碼

( jupyter notebook: Here )

如果這篇文章有幫助到你,可以幫我在下方綠色的拍手圖示按5下,只要登入Google或FB,不需任何花費就能【免費支持】youmgmi 繼續創作。

--

--

Youngmi huang
PyLadies Taiwan

Participate in data science field, fascinated by something new. (Current: fraud risk modeling with ML/DL, Past: NLP)