前期工作
我的目標是利用tenserflow得到一個可以對新聞標題進行準確分類的分類器。
首先我需要有新聞標題的原始數據,因此我從今日頭條抓取了近十萬條新聞標題用于接下來的訓練工作。
得到原始標題數據后,我需要對其進行分詞構建語料庫,分詞我使用jieba這個第三方庫。
之后要通過語料庫用Word2vec算法對分詞進行訓練,這里我使用gensim的word2vec。
梳理下準備條件:
- 原始新聞標題數據
- jiaba
- gensim
生成語料文件
我抓取的數據存放在MYSQL,因此我將查詢出標題進行分詞后寫入語料文件:yuliao.txt。
path = sys.path[0]
yuliao_path = os.path.join(path, 'yuliao.txt') # 生成語料的路徑
def filter_biaodian(cnt):
pat = r'[?。?"?!纾ィΓВǎ?,-/:;<=>@[\]^_`{|}~?????、〃《》「」『』【】〔〕〖〗?????〝〞????–—‘’?“”??…?﹏.]+|[!"#$%&\'()*+,-./:;<=>?@\[\\\]\^\_\`\{\|\}\~0-9]+'#去標點
return re.sub(pat, '', cnt)
def filter_kong(x):
if ' ' in x:
return False
return True
def title_handle(title):
# 去除標點符號
title = filter_biaodian(title)
title = ' '.join(list(filter(filter_kong, jieba.lcut(title)))) + ' '
return title
def load_data():
sql = '''
select title from ToutiaoNews
'''
res = db.execute_sql(sql)
with open(yuliao_path, 'w') as fp:
for title in res:
title = title_handle(title[0])
fp.write(title)
雖然jieba分詞已經很不錯了,但是對于某些熱門新詞和人名等還是不夠準確,所以有必要自定義一些詞匯提供給jieba。
我在user_dict.txt中定義了一些jieba沒有正確分出來的詞:
C羅
王思聰
陳意涵
王晶
四驅
楊超越
高穎浠
李子璇
熱依娜
摩拜
發(fā)威
余額寶
小鮮肉
然后加載到我們的程序中:
# 加載自定義字典
dict_path = os.path.join(path, "user_dict.txt")
jieba.load_userdict(dict_path)
執(zhí)行load_data方法便會生成語料文件。
訓練和保存模型
導入gensim,加載我們的語料文件,開始訓練模型:
from gensim.models import word2vec
# 模型文件存放路徑
model_path = os.path.join(path, "word2vec_model.bin")
def train_model():
print('加載語料文件...')
sentences =word2vec.Text8Corpus(yuliao_path) # 加載語料
print('模型訓練中...')
model =word2vec.Word2Vec(sentences, size=200) #訓練skip-gram模型,默認window=5
# 保存模型,以便重用
print('保存模型文件中...')
model.save(model_path)
訓練好模型保存為文件,下次可以直接從文件導入,不必再進行訓練。
def load_word2vec_model():
'''
加載訓練好的模型
'''
print('加載模型文件...')
return word2vec.Word2Vec.load(model_path)
def print_most_similar(words):
'''
測試輸出最相關的20個詞
'''
model = load_word2vec_model()
y2 = model.most_similar(words, topn=20) # 20個最相關的
print ("-------------")
print('>>> 和 {} 最相關的20個詞:\n'.format(words))
for item in y2:
print(item[0], item[1])
print ("-------------")
我們看下模型的效果,運行print_most_similar測試方法,輸出:
-------------
>>> 和 人工智能 最相關的20個詞:
前景 0.9870855212211609
應用 0.986504077911377
推動 0.9858032464981079
觀察 0.9855602979660034
機器人 0.9849052429199219
共享 0.9845559000968933
展銳 0.9841729402542114
發(fā)展趨勢 0.9837538599967957
指數 0.9834417700767517
金服 0.9829524159431458
進一步 0.9829222559928894
高質量 0.9827390909194946
解讀 0.9825021624565125
趨勢 0.9823193550109863
實體 0.9820591807365417
各大 0.9819753170013428
物流 0.9819672107696533
生態(tài) 0.9815815687179565
房地產 0.981529712677002
運營 0.9815083742141724
-------------
效果還可以,如果語料再多一點會更好。
詞向量
訓練好的模型相近意思的詞在向量空間中的位置也是相似的,這樣我們依據詞向量做分類訓練,本質上是將相近意思的句子歸類。
當然最終我們要得到某個詞的向量表示形式:
if __name__ == '__main__':
model = load_word2vec_model()
print('model type:', type(model))
print(model['ofo'])
print('model size of ofo:', len(model['ofo']))
print('the type of an element of the ofo:', type(model['ofo'][0]))
out:
加載模型文件...
--> model type: <class 'gensim.models.word2vec.Word2Vec'>
[-0.12093621 0.21866739 0.0476281 0.15949744 -0.2265305 -0.08501934
0.1477401 -0.00190862 -0.03246938 -0.06177654 0.14871995 0.19064938
0.20575511 -0.12488797 0.18135293 0.17202124 -0.09171224 -0.21369526
0.03578532 -0.08414337 -0.04215271 -0.07621672 0.22449629 0.0337574
-0.01039878 0.01468771 0.15081759 0.09702738 -0.33268988 0.11885371
-0.16769075 0.09913398 -0.0534218 0.15699175 -0.10522668 0.02929186
0.15697408 0.10360114 -0.22695963 -0.09760883 -0.06047406 0.20749298
0.16786923 -0.32377186 -0.0979296 0.23040165 -0.06727723 0.2789535
-0.05251723 0.05750585 0.04498681 -0.19886209 -0.14110063 -0.43698636
0.31315592 -0.0539036 0.18757886 -0.12233631 0.25112468 -0.12556228
-0.19618745 0.23073478 0.09799167 -0.09279976 -0.13416637 -0.30544615
0.20916344 0.18377133 -0.20380071 0.06745876 0.22611332 -0.11335444
-0.30527177 -0.0248933 0.01644903 -0.09095342 0.17283195 -0.11239095
-0.01026074 -0.11678243 -0.20007738 -0.00843141 0.12541942 0.08090381
0.13402799 -0.25427282 0.00226124 -0.11637224 -0.07989754 0.09807675
-0.01441371 -0.13024434 -0.15721492 -0.21402866 0.04589665 -0.06763294
-0.17075238 -0.07745436 0.0095577 -0.38303027 0.07163925 0.38283527
0.25002772 0.32608908 0.13308333 0.24943127 0.03098303 0.03559564
-0.05252191 -0.01458469 0.14649096 0.17111804 0.1398329 -0.06161319
0.0758339 0.01116067 -0.1789481 -0.39118966 0.02592629 0.11360105
-0.12705195 -0.09707507 0.20374824 0.20948473 0.189067 -0.08490008
0.03691229 -0.03789151 0.09222446 0.36308745 -0.11168318 0.04258949
-0.04875926 -0.06543283 -0.05993763 -0.21278009 0.15429844 -0.03047387
0.08654932 -0.27806106 0.13747326 -0.3273331 -0.18196188 -0.20869672
0.19920668 0.16047722 -0.22706664 0.14389433 0.12567239 -0.2691268
-0.20942092 -0.0147821 -0.14789784 -0.04505106 -0.17953952 0.00555091
-0.02158411 0.21042849 -0.10467305 -0.01584556 -0.08712497 0.01285077
0.13214627 -0.05077496 0.20669343 0.25896493 0.14283897 -0.06721289
-0.13196066 -0.04882697 0.02222396 0.00217219 0.11299089 -0.09901663
-0.15670624 -0.13901645 0.1034102 0.15072429 0.42944327 0.02470743
0.11724957 0.09513479 -0.1651883 0.12621285 0.17963493 0.09137619
0.02091281 -0.04587717 0.0837699 -0.14793368 0.13413116 0.01136413
-0.31699035 0.03399559 0.06288019 -0.05555357 0.11239031 -0.07564677
0.08233534 0.1478644 ]
--> model size of ofo: 200
--> the type of an element of the ofo: <class 'numpy.float32'>