123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- # coding: utf-8
- """
- Rewritten from Github
- """
- import jieba
- import matplotlib.pyplot as plt
- import numpy as np
- import random
- from PIL import Image
- from wordcloud import WordCloud
- from scipy.ndimage import gaussian_gradient_magnitude
- # Load
- text = """
- 在我的筆電鍵盤上,F11 和 F12 一直都是調整螢幕亮度的快捷鍵,就像下面這張圖片一樣:
- 不過這個圖示好看歸好看,但是在我的筆電上從來都沒辦法用他們來調整螢幕亮度 (正常的 F11、F12 功能還是可以用)。為了保險起見,我還使用 xev 測試看看有沒有抓到 Keycode,不過自然是抓得到的。
- 今天想要紀錄的就是,我如何將這兩個按鍵設置為調整螢幕亮度的快捷鍵,搞不好會有一樣問題的人可以參考看看。
- 在我的系統上,我的亮度設定是位於 “/sys/class/backlight/intel_backlight/” 這個路徑底下。你的路徑可能與我不同,不過大致上都會在 “/sys/class/backlight/” 底下。
- 其中,max_brightness 是我系統上可以設定的亮度最大值,為 120000;brightness 則是我系統當前設定的值,只要更動這個檔案內的數值,我電腦螢幕的亮度也會隨之改變。
- 所以要做的第一件事情,就是將 brightness 這份檔案設定權限,讓我可以在一般模式時就能寫入它。
- 若是我要減少亮度,我可以使用以下指令:
- 若是我要提昇亮度,則就將 “-” 換成 “+” 即可。
- 確認這兩個指令沒有問題,就可以將其設定為快捷鍵了。
- 其實設定快捷鍵也是相當簡單,在此我簡單做個示範、不過大部份桌面環境設定快捷鍵的方式都大同小異。
- 基本上,搜尋 “Shortcut”,應該就能直接找到設定快捷鍵的地方。
- 設定快捷鍵有三個參數要填入: Name、Command、Shortcut。
- Name: 無所謂,填入喜歡的名稱即可
- Command: 填入上方調整螢幕亮度的指令
- Shortcut: 按下你想要的快捷鍵,以我這裡為例便是 F11、F12
- 完成設置後,我就能成功假裝我的按鍵是正常可以用的了 XDD
- 在 Python 中,我們若是想要將一段文本依照『特定字元』來切割,讓文本變成一段段的 List 資料型態儲存著,我們可以簡單地使用 split() 這個函式來完成。
- 而 splitlines() 這個函式與 split() 非常相像,不過 splitlines() 是專門處理換行符號的,並且在處理時還能選擇是否保留著換行符號,非常好用。
- 假設我們有著以下這樣的文本:
- 假設我們想要以空格符號 ” ” 為切割點,我們得到的結果應如下:
- for word in text.split():
- print(word)
- Output:
- 除了預設的以『空格符號』切割外,我們也可以自己選擇換行符號 “\n” 來進行切割。
- Today is a nice day.
- This is a good day.
- Hello! How are you?
- 不過在以換行符號 “\n” 切割的時候,split() 是沒有比 splitlines() 方便的,以下我們就來看看 splitlines() 的範例。
- splitlines() 比 split() 優秀的地方在於,我們的文本中很有可能並不僅僅只存在著 “\n” 這樣單純的換行, “\r”、”\r\n”、”\n” 等等也都會被視作換行。
- 根據我的經驗,同時考慮 “\r”、”\r\n”、”\n” 三種情況的切割點效果比較好,畢竟不會出現應該換行卻沒有被切割的句子。
- 同時,splitlines() 還可以透過 keepends 參數決定是否在輸出結果中保留『換行符號』,在某些情況是非常有用的。
- '\n'
- 'Today is a nice day.\n'
- 'This is a good day.\n'
- 'Hello! How are you?\n'
- 這裡我使用了 pprint 來顯示換行符號。值得一提的是 keepends 若為 True 表示保留換行符號;反之,則不保留。
- 使用 FastText 訓練詞向量
- FastText 是由 Facebook AI Research Lab (FAIR) 所開發的『詞嵌入』以及『文本分類』,支援 294 種語言,並且使用類神經網路訓練詞嵌入模型。
- 基本上 FastText 的演算法是基於以下這兩篇論文:
- Enriching Word Vectors with Subword Information
- Bag of Tricks for Efficient Text Classification
- 不過介紹了這麼多,今天我主要的目的是要介紹如何在 Python 中透過 Gensim 套件快速地調用 FastText 訓練一個 Word Embedding 的模型。基本上流程都與 Gensim 中本來訓練 Word2Vec 極度相像。
- 以下就直接來看程式碼。值得一提的是,由於我之前寫過使用 Gensim 訓練 Word2Vec 模型,所以有部份相同的流程我是直接從那邊抄來的 XDD
- 安裝 Gensim
- 首先,如果你的環境裡沒有 Gensim,使用以下指令安裝:
- pip3 install gensim
- Python is the most popular programming language!
- 前言
- FastText 是由 Facebook AI Research Lab (FAIR) 所開發的『詞嵌入』以及『文本分類』,支援 294 種語言,並且使用類神經網路訓練詞嵌入模型。
- 基本上 FastText 的演算法是基於以下這兩篇論文:
- Enriching Word Vectors with Subword Information
- Bag of Tricks for Efficient Text Classification
- 不過介紹了這麼多,今天我主要的目的是要介紹如何在 Python 中透過 Gensim 套件快速地調用 FastText 訓練一個 Word Embedding 的模型。基本上流程都與 Gensim 中本來訓練 Word2Vec 極度相像。
- 以下就直接來看程式碼。值得一提的是,由於我之前寫過使用 Gensim 訓練 Word2Vec 模型,所以有部份相同的流程我是直接從那邊抄來的 XDD
- 安裝 Gensim
- 首先,如果你的環境裡沒有 Gensim,使用以下指令安裝:
- pip3 install gensim
- 下載 WIKI 語料
- 這裡以 Wiki 上的中文資料為訓練語料,Wiki 上的資料可是相當優秀的。不僅量多、而且詞彙涵蓋範圍廣,可以應用在許多不同的任務上。
- 可以從這個網址找到下載處:https://zh.wikipedia.org/wiki/Wikipedia:%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%8B%E8%BD%BD
- 進入之後可以直接選擇一個日期,那是不同時間點的資料備份。
- 比如說我選擇了 20200101 這個時間點的資料,那麼,我要下載的資料則為:zhwiki-20200101-pages-articles-multistream.xml.bz2
- 要注意的是,你的日期可能與我不同,不過同樣都是這份檔案。
- 下載之後不用解壓縮,可以使用 Gensim 裡的工具直接提取文章。
- WikiCorpus
- WikiCorpus 是 Gensim 裡面的一個模組,專門用於清理 Wiki 資料庫中語料不必要的標籤,使其恢復成乾淨的文本。
- # coding: utf-8
- Extracted the content in the wiki_database
- from gensim.corpora import WikiCorpus
- # Load data
- wiki_corpus = WikiCorpus('../data/zhwiki-latest-pages-articles-multistream.xml.bz2', dictionary={})
- # Save data
- with open('wiki_text.txt', 'w', encoding='utf-8') as f:
- print('Start to preprocess.')
- for times, text in enumerate(wiki_corpus.get_texts()):
- f.write(' '.join(text)+'\n')
- if (times+1) % 10000 == 0:
- print(times+1)
- 順帶一提,WikiCorpus() 函式當中的路徑為我下載的語料資料,你的名稱可能與我不同、也需要對應到你下載的路徑。
- 儲存之後的效果應如下:
- 斷詞
- 『斷詞』這項工作指的是文本分成以『詞』為單位的句子。斷詞的工具有很多種,基本上可以參考我之前寫過的:
- NLP 繁體中文斷詞的霸主 —— CKIP
- NLP 中文斷詞最方便的開源工具之一 —— Jieba
- 中文自然語言分析的工具包 —— THULAC
- 多功能的自然語言處理工具 —— HanLP
- 如果想要對繁體中文斷詞效果最好,首推 CKIP;如果是要斷詞速度的話,那非 Jieba 莫屬。在這裡以 Jieba 示範。
- (註:Wiki 的資料當中許多地方是簡繁混雜的,可以考慮使用 OpenCC 這項工具來轉換。詳細的作法可以參閱我之前撰寫過的《中文繁簡轉換的便利工具 —— OpenCC》)
- # coding: utf-8
- Tokenize
- import jieba
- from opencc import OpenCC
- # Initial
- cc = OpenCC('s2t')
- # Tokenize
- with open('wiki_text_seg.txt', 'w', encoding='utf-8') as new_f:
- with open('wiki_text.txt', 'r', encoding='utf-8') as f:
- for data in f:
- data = cc.convert(data)
- data = jieba.cut(data)
- data = [word for word in data if word != ' ']
- data = ' '.join(data)
- new_f.write(data)
- 斷詞結果展示如下:
- 歐幾
- 裏
- 得
- 西元前
- 三世
- 紀的
- 古希臘
- 數學家
- 現在
- 被
- 認為
- 是
- 幾何
- 之父
- 此畫
- 為拉斐爾
- 的
- 作品
- 雅典
- 學院
- 數學
- 是
- 利用
- …
- 最後,終於來到呼叫 FastText 來訓練模型了。
- 使用 FastText 訓練模型
- # coding: utf-8
- from gensim.models import word2vec, fasttext
- # Settings
- seed = 666
- sg = 0
- window_size = 10
- vector_size = 100
- min_count = 1
- workers = 8
- epochs = 5
- batch_words = 10000
- # Train
- train_data = word2vec.LineSentence('wiki_text_seg.txt')
- model = fasttext.FastText(
- train_data,
- min_count=min_count,
- size=vector_size,
- workers=workers,
- iter=epochs,
- window=window_size,
- sg=sg,
- seed=seed,
- batch_words=batch_words,
- )
- model.save('fasttext.model')
- 這裡也解釋一下模型中各個參數的意義:
- seed: 亂數種子
- sg: Word2Vec 有兩種算法,CBOW 以及 Skip-gram,這裡選擇了訓練比較快的 CBOW
- window_size: 周圍詞彙要看多少範圍
- size: 轉成向量的維度
- min_count: 詞頻少於 min_count 之詞彙不會參與訓練
- workers: 訓練的並行數量
- iter: 訓練的迭代次數
- batch_words:每次給予多少詞彙量訓練
- 訓練結束以後,我將模型儲存為 “fasttext.model”。
- 測試模型效果
- # coding: utf-8
- Test the w2v model
- from gensim.models import word2vec
- # Load the model
- model = word2vec.Word2Vec.load('models/fasttext.model')
- # Test
- print(model['生物'].shape)
- for item in model.most_similar('生物'):
- print(item)
- model.save('fasttext.model')
- Output:
- (100,)
- ('若好', 0.9359757900238037)
- ('身半', 0.9298930764198303)
- ('過金', 0.9281899929046631)
- ('低等生物', 0.9252755641937256)
- ('腐生物', 0.9232699275016785)
- ('過金魅', 0.9228056073188782)
- ('生物能', 0.9225305914878845)
- ('捉酸蟲', 0.9221773743629456)
- ('非生物', 0.9185526371002197)
- ('過金貝', 0.9147799015045166)
- 不知道是不是我的錯覺,我覺得 Gensim 訓練 Word2Vec 模型感覺效果比較好。
- """
- # Tokenize
- text = ' '.join(jieba.cut(text))
- # Mask image
- mask_color = np.array(Image.open('./parrot-by-jose-mari-gimenez2.jpg'))
- mask_color = mask_color[::3, ::3]
- mask_image = mask_color.copy()
- mask_image[mask_image.sum(axis=2) == 0] = 255
- # Edge detection
- edges = np.mean([gaussian_gradient_magnitude(mask_color[:, :, i]/255., 2) for i in range(3)], axis=0)
- mask_image[edges > .08] = 255
- # WordCloud
- wc = WordCloud(max_words=2000,
- mask=mask_image,
- # font_path='fonts/DFXingKaiStd-W5.otf',
- max_font_size=40,
- random_state=42,
- relative_scaling=0)
- wc.generate(text)
- # Create coloring from image
- def color_func(word, font_size, position, orientation, random_state=None, **kwargs):
- return 'hsl(51, 100%%, %d%%)' % random.randint(40, 60)
- wc.recolor(color_func=color_func)
- # Plot
- plt.figure()
- plt.axis('off')
- plt.imshow(wc)
- plt.show()
- # Save
- plt.figure()
- plt.axis('off')
- fig = plt.imshow(wc, interpolation='nearest')
- fig.axes.get_xaxis().set_visible(False)
- fig.axes.get_yaxis().set_visible(False)
- plt.savefig('test.png',
- bbox_inches='tight',
- pad_inches=0,
- format='png',
- dpi=300)
|