iT邦幫忙

2022 iThome 鐵人賽

DAY 13
2
AI & Data

文理組人都能上手的入門 NLP(自然語言處理)系列 第 14

[Day 13] 資料視覺化實作:把斷詞結果變成比文字雲更酷炫的文字狗跟文字小新

  • 分享至 

  • xImage
  •  

  早安各位,今天是還債日。之前在講斷詞斷句的時候有提到要出一個文字雲教學,但是因為時間安排的關係就被移到今天了。廢話不多說,大家應該都看過文字雲吧?就是下面那個把詞聚在一起變成塊狀物的東西,通常越重要(詞頻越高)的詞就會越中間越大,可以用來讓其他人一眼看出重點。其實有滿多網站提供線上生成文字雲的工具跟服務,但那是外行人在用的東西啦。既然你各位現在都有程式基礎也會自己斷詞了,畫個文字雲根本難不倒,甚至你對它的形狀或顏色有甚麼期待都可以靠python的套件跟簡單的幾行程式碼解決。自己動手,豐衣足食。相信我,看完這篇文章,你再也不會想去用那些線上工具了(怎麼突然有點像在賣藥

  今天要請出的厲害套件就是wordcloud,為什麼要說他厲害呢?後面你就會知道了,他根本就是披著python套件皮的修圖軟體。在體驗它的酷炫功能之前,我們先試著做出一個最default的文字雲吧。wordcloud真的非常之貼心,我們直接把字串放進去他就會幫我們斷好詞了,所以我們只要把它跟用來畫圖的套件matplotlib引進python就可以了。(我這次用的是這篇新聞

!pip install matplotlib
import matplotlib.pyplot as plt
from wordcloud import WordCloud
eng_news = open("/content/eng_news.txt").read()

  接下來使用WordCloud裡面的generate()函式就可以初步生成文字雲了。文字雲生成之後再用matplotlib裡面的imshow()讓圖片顯現出來就完成最簡易的文字雲啦~

wordcloud = WordCloud().generate(eng_news)
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")

  imshow()的第二個參數是為了讓圖片印出來畫素比較好的必需品,所以雖然你可能不懂它的意思,還是記得要加上去。然後axis指的是橫軸座標跟縱軸座標。因為我們不是在畫統計圖表,所以不需要它。這些東西都設定好之後就可以印出下面這張圖。

https://ithelp.ithome.com.tw/upload/images/20220927/20151687PMp2lPYIJz.png

參數調整

  怎麼說呢?上面確實是一個合格的文字雲,就是看起來有點無聊。啊哈!我們放著WordCloud()裡面那麼多可以調的參數不管,也難怪這個文字雲這麼無聊了。下面介紹幾個你可能會想用到的參數:

參數 作用 格式
width 設定圖片長度 預設值是400
height 設定圖片高度 預設值是200
scale 設定圖片要放大的倍數 預設值是1
stopwords 設定停止詞 可以用set(STOPWORDS)叫出default字典
fontfile 更換字型 輸入字型檔案的路徑
margin 調整文字之間的間隔 預設值是2
background_color 更換背景顏色 十六進位色碼
colormap 更換字顏色的主題 主題名稱
max_words 設定文字雲容納字數的上限 預設值是200
min_font_size 設定最小的字體大小 預設值是4
max_font_size 設定最大的字體大小 數值
no_normalize_plurals 要不要把複數跟單數詞看成同一個 預設值是True

  這些都是比較基礎,大家可以視自己需求調整的參數(完整列表),下面我稍微示範一下怎麼做:

from wordcloud import STOPWORDS, ImageColorGenerator
stopword = set(STOPWORDS)
wordcloud = WordCloud(width = 4000, height = 3000, stopwords = STOPWORDS, margin = 3, background_color = "white", colormap = "Set3", max_words = 25, min_font_size = 8).generate(eng_news)

https://ithelp.ithome.com.tw/upload/images/20220927/20151687cvijOrpaBy.png

  嗯嗯這樣看起來賞心悅目多了(至少對我來說啦 XDD)

形狀調整

  什麼?!你說為什麼文字雲不是雲的形狀?因為文字雲本來就只是一個隱喻的說法啊。不過既然你都這麼說了,我們就來介紹一下wordcloud提供的遮罩功能吧。給大家看一下官方demo的遮罩功能產物:
http://amueller.github.io/word_cloud/_images/sphx_glr_masked_001.png

  都可以做成這樣了,雲根本是一塊蛋糕好嗎。如果想要一朵雲的話,首先要找到一張雲的圖片。不是隨便一張圖喔,是一張雲本身的輪廓跟背景顏色分界明顯的圖片。像是這個:
https://cdn2.vectorstock.com/i/1000x1000/84/11/cloud-cute-cartoon-vector-22728411.jpg

  有了圖之後,我們還需要一個可以把圖片引進來的套件(Pillow)跟把上面的顏色資料傳換成數值的套件(numpy)才能開始。Image.open()Pillow裡面用來讀入圖片的函式。我們把圖片讀進來以後再用array()幫圖片做一維數值轉換,讓它變成電腦可以讀懂的數字。

import numpy as np
from PIL import Image
mask = np.array(Image.open("/content/cloud-cute-cartoon-vector-22728411.jpg"))

  有了這個東西之後我們就可以加入遮罩的參數讓WordCloud幫我們畫出「真正的」文字雲。

real_wordcloud = WordCloud(mask = mask, stopwords = STOPWORDS, margin = 3, contour_color='#023075', contour_width=3, background_color = "white", colormap = "Set3", max_words = 25, min_font_size = 8).generate(eng_news)
plt.imshow(real_wordcloud, interpolation='bilinear')
plt.axis("off")

https://ithelp.ithome.com.tw/upload/images/20220927/201516870tD1tFGM3f.png

  好啦你現在可能在想說為什麼這個看起來那麼小,畫質那麼差,這是因為matplotlib預設的imshow()顯示是800*600,所以不管我們WordCloud()裡面的參數再怎麼調,它都只會是那個大小。So~我們要在下面加上一個調整imshow顯示的函式。這次換隻狗來試試好了。

worddog = WordCloud(width = 1000, height =800, mask = mask, stopwords = STOPWORDS, margin = 3, scale = 10, background_color = "white", colormap = "Set3", min_font_size = 8).generate(eng_news)
plt.figure( figsize=(20,10) ) #新加的函式在這裡
plt.imshow(worddog, interpolation='bilinear')
plt.axis("off")

  Do rei mi so (づ ̄ 3 ̄)づ 這樣就完美了~

https://ithelp.ithome.com.tw/upload/images/20220927/20151687ozSmCUAEug.png

跟著圖片色調走

  現在覺得上面的功能很酷還太早了,如果你對於要幫文字雲上什麼顏色很煩惱的話,可以考慮用下面這個功能。在我們用WordCloud初步產出的文字雲裡面,其實藏有一個叫做recolor的函式,在我們用ImageColorGenerator擷取圖片的顏色分布之後,可以把它拿來當整個文字雲的上色依據,像是下面這樣:

shin = WordCloud(width = 900, height =1600, mask = mask, stopwords = STOPWORDS, margin = 3, scale = 10, background_color = "white", min_font_size = 8).generate(eng_news)
image_colors = ImageColorGenerator(mask)
plt.figure( figsize=(20,10) )
plt.imshow(shin.recolor(color_func=image_colors), interpolation="bilinear")
plt.axis("off")

https://ithelp.ithome.com.tw/upload/images/20220927/201516873YiTsxcZIG.png

  看看這個熟悉的配色,上紅下黃,除了小新還能是誰?
https://ithelp.ithome.com.tw/upload/images/20220927/20151687xqqBdPqkrs.png

中文文字雲

  說了那麼多,都是用英文當例子也太有損我中文母語者的身分了。因為wordcloudmatplotlib都是外國人設計的,當然沒有考慮其他語言的使用者。除了我們要自己先斷詞之外,為了讓中文可以順利顯示在上面,還要多加幾個步驟。(好啦其實有啦,人家有在官網上面demo怎麼做中文的文字雲)

  首先,我們要做的事情就是到google fonts上面下載中文字型,再弄到colab裡面。當然如果你自己電腦裡面有想用的字型也可以把檔案傳到colab上面,總之就是要有一個字型檔就對了。

font_path = '/content/Iansui0.93-Regular.ttf'
ch_news = " ".join(ckip_clean_result) # 把串列裡的字串用空格結合起來
ch_wordcloud = WordCloud(font_path = font_path, width = 900, height =1600, mask = mask, stopwords = STOPWORDS, margin = 3, scale = 10, background_color = "white", min_font_size = 8, prefer_horizontal = 1).generate(ch_news)

  上面這個是我已經先用ckiptagger斷好詞的結果,因為英文斷詞的方式就是找空格的地方,所以我們把串列裡面的字串用空格連接起來就可以丟給WordCloud內建的斷詞器斷詞了。斷詞器裡面只要多加上font_path這個參數指定要使用的字型檔案路徑就能讓中文顯現出來。同理,如果你不滿意預設的英文字體當然也可以用這個方式把他換掉。接下來一樣用matplotlib把圖印出來就可以了。BTW 如果你不喜歡字被轉來轉去,可以跟我一樣加上prefer_horizontal = 1去固定他的旋轉角度。

plt.figure( figsize=(20,10) )
plt.imshow(ch_wordcloud.recolor(color_func=image_colors), interpolation="bilinear")
plt.axis("off")

https://ithelp.ithome.com.tw/upload/images/20220927/201516871bXZSy4wEv.png

  想不到吧,光是一個文字雲我竟然可以打這麼多東西。(我自己都沒想到)總是這就是畫出很fancy的文字雲的方法啦~下次不要再用網路上那些簡陋的工具了,按照個人喜好弄個有趣的文字雲來跟朋友炫耀一下吧~明天見!


參考資料

wordcloud官方
提高清晰度的方法


上一篇
[Day 12] 時間都去哪了?資料前處理:抓住那個欠錢不還的傢伙-詞性標註之HMM的應用
下一篇
[Day 14] 機器學習常用特徵:超級變變變 -BOW 詞袋模型
系列文
文理組人都能上手的入門 NLP(自然語言處理)31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言