中文文本預處理完整流程(附代碼)
標籤:中文文本預處理
作者:煉己者
摘要
- 機器學習我的理解就是把各種原始的東西變成機器可以理解的東西,然後再用各種機器學習演算法來做操作。機器可以理解的東西是什麼呢?——向量 。所以不管是圖片還是文字,要用機器學習演算法對它們進行處理,就要把它們轉為向量。
- 網上大部分都是處理英文文本的資料,本文就以中文文本為例,將原始的文本經過預處理得到文本向量
目錄
- 去除指定無用的符號
- 讓文本只保留漢字
- 對文本進行jieba分詞
- 去除停用詞
- 將文本轉為tfidf向量並輸入到演算法中
操作流程
1.去除指定無用的符號
我們拿到的文本有時候很有很多空格,或者你不想要的符號,那麼你就可以用這個方法去掉所有你不想要的符號。在這裡我以空格為例
content = [ 歡迎來到 煉己者的博客,煉己者 帶你入門NLP ]
# 去掉文本中的空格
def process(our_data):
m1 = map(lambda s: s.replace( , ), our_data)
return list(m1)
print(process(content))
傳入的參數our_data是個列表,此函數可以把文本中的所有空格全部去掉。看一下輸出的結果。可以發現,所有的空格都被刪掉了
[歡迎來到煉己者的博客, 煉己者帶你入門NLP]
2.讓文本只保留漢字
這個操作我最喜歡,他可以去掉所有的符號,包括數字、標點、字母等等
content = [如果這篇文章對你有所幫助,那就點個讚唄!!!,如果想聯繫煉己者的話,那就打電話:110!!!,想學習NLP,那就來關注呀!^-^]
# 讓文本只保留漢字
def is_chinese(uchar):
if uchar >= uu4e00 and uchar <= uu9fa5:
return True
else:
return False
def format_str(content):
content_str =
for i in content:
if is_chinese(i):
content_str = content_str + i
return content_str
# 參函數傳入的是每一句話
chinese_list = []
for line in content:
chinese_list.append(format_str(line))
print(chinese_list)
然後我們來看一下輸出的內容,你會發現只剩下中文了。這個操作實在太騷了
[如果這篇文章對你有所幫助那就點個讚唄, 如果想聯繫煉己者的話那就打電話, 想學習那就來關注呀]
3. 對文本進行jieba分詞
首先你得下載jieba這個庫,直接pip install jieba即可。 我們就以上面處理好的那句話作為例子來操作
chinese_list = [如果這篇文章對你有所幫助那就點個讚唄, 如果想聯繫煉己者的話那就打電話, 想學習那就來關注呀]
# 對文本進行jieba分詞
import jieba
def fenci(datas):
cut_words = map(lambda s: list(jieba.cut(s)), datas)
return list(cut_words)
print(fenci(chinese_list))
然後你就可以得到分詞的結果了
[[如果, 這, 篇文章, 對, 你, 有所, 幫助, 那, 就, 點個, 贊, 唄],
[如果, 想, 聯繫, 煉己, 者, 的話, 那, 就, 打電話],
[想, 學習, 那, 就, 來, 關注, 呀]]
4.去除停用詞
首先你得上網下載一個停用詞表,也可以關注我的微信公眾號: ZhangyhPico,回復停用詞表,就可以拿到了。然後把這份停用詞轉換為列表 為了方便大家理解,在這裡我就假設一個停用詞表了,我們以上面分好詞的數據為例
# 分好詞的數據
fenci_list = [[如果, 這, 篇文章, 對, 你, 有所, 幫助, 那, 就, 點個, 贊, 唄],
[如果, 想, 聯繫, 煉己, 者, 的話, 那, 就, 打電話],
[想, 學習, 那, 就, 來, 關注, 呀]]
# 停用詞表
stopwords = [的,呀,這,那,就,的話,如果]
# 去掉文本中的停用詞
def drop_stopwords(contents, stopwords):
contents_clean = []
for line in contents:
line_clean = []
for word in line:
if word in stopwords:
continue
line_clean.append(word)
contents_clean.append(line_clean)
return contents_clean
print(drop_stopwords(fenci_list,stopwords))
我們來一下結果,對比發現少了一些停用詞
[[篇文章, 對, 你, 有所, 幫助, 點個, 贊, 唄],
[想, 聯繫, 煉己, 者, 打電話],
[想, 學習, 來, 關注]]
我覺得上面的操作也可應用在去除一些你不想要的符號上面,你可以把沒有用的符號添加到停用詞表裡,那麼它也會被去掉
5.將文本轉為tfidf向量並輸入到演算法中
最後這一步你可以參照這篇文章操作,使用不同的方法計算TF-IDF值 不過為了完整起見,我在這裡給大家再演示一遍操作流程。咱們就以上面去掉停用詞的數據為例
word_list = [[篇文章, 對, 你, 有所, 幫助, 點個, 贊, 唄],
[想, 聯繫, 煉己, 者, 打電話],
[想, 學習, 來, 關注]]
from gensim import corpora,models
dictionary = corpora.Dictionary(word_list)
new_corpus = [dictionary.doc2bow(text) for text in word_list]
tfidf = models.TfidfModel(new_corpus)
tfidf_vec = []
for i in range(len(words)):
string = words[i]
string_bow = dictionary.doc2bow(string.split())
string_tfidf = tfidf[string_bow]
tfidf_vec.append(string_tfidf)
print(tfidf_vec)
在這裡我們就可以得到tfidf向量,這裡調用的是gensim庫計算的tfidf向量,你也可以直接調用sklearn庫來計算tfidf向量,怎麼操作看上面的那篇文章,裡面都有介紹。我們來看一下得到的tfidf向量長什麼樣子
[[(0, 0.35355339059327373),
(1, 0.35355339059327373),
(2, 0.35355339059327373),
(3, 0.35355339059327373),
(4, 0.35355339059327373),
(5, 0.35355339059327373),
(6, 0.35355339059327373),
(7, 0.35355339059327373)],
[(8, 0.18147115159841573),
(9, 0.49169813431045906),
(10, 0.49169813431045906),
(11, 0.49169813431045906),
(12, 0.49169813431045906)],
[(8, 0.2084041054460164),
(13, 0.5646732768699807),
(14, 0.5646732768699807),
(15, 0.5646732768699807)]]
很明顯,句子的長度不一樣,所以得到的tfidf向量的維度也不一樣。那麼我們該怎麼操作呢?——可以用lsi向量來保證向量的維度一致
# num_topics參數可以用來指定維度
lsi_model = models.LsiModel(corpus = tfidf_vec,id2word = dictionary,num_topics=2)
lsi_vec = []
for i in range(len(words)):
string = words[i]
string_bow = dictionary.doc2bow(string.split())
string_lsi = lsi_model[string_bow]
lsi_vec.append(string_lsi)
print(lsi_vec)
看一下結果
[[(1, 2.8284271247461907)],
[(0, 1.6357709481422218)],
[(0, 1.4464385059387106)]]
sklearn庫的機器學習演算法很齊全,你可以調用這些演算法包來進行操作。但是sklearn里的演算法要求數據的格式必須是array格式,所以我們得想辦法把gensim計算的tfidf向量格式轉化為array格式。按照下面操作即可
from scipy.sparse import csr_matrix
data = []
rows = []
cols = []
line_count = 0
for line in lsi_vec:
for elem in line:
rows.append(line_count)
cols.append(elem[0])
data.append(elem[1])
line_count += 1
lsi_sparse_matrix = csr_matrix((data,(rows,cols))) # 稀疏向量
lsi_matrix = lsi_sparse_matrix.toarray() # 密集向量
print(lsi_matrix)
結果長這樣
array([[0. , 2.82842712],
[1.63577095, 0. ],
[1.44643851, 0. ]])
我們的目的已經達到。肯定有人會問,你為啥不直接調用sklearn里計算tfidf向量的方法,那多方便,多直接。何必這樣轉換來轉換去的。
這是有原因的,假設你的數據量很大,幾百萬條,那麼用sklearn計算的tfidf向量維度會非常大,最後調用機器學習演算法包的時候就會報錯。如果你調用gensim來計算tfidf向量,然後再採用上述的方法,就可以對向量進行降維了,而且你還可以指定維度。在lsi向量那一步進行操作,num_topics參數可以用來指定維度
總結
以上便是整個中文文本的預處理了,這個流程可以應付大多數的文本處理任務。你把文本轉換為向量之後,後面的操作就很容易了,調用sklearn演算法包,或者自己寫一個機器學習的演算法,這些都是有章法可循的。
希望可以幫助到大家,如果你覺得這篇文章對你有一定的幫助,那就點個贊支持一下吧!如果有什麼問題的話也可以在文章下面評論,我們一起交流解決問題!
推薦閱讀: