GolVe向量化做文本分類

全文共2369個字,預計閱讀時間12分鐘。

向量化

在之前,我對向量化的方法一直侷限在兩個點,

第一種是常規方法的one-hot-encoding的方法,常見的比如tf-idf生成的0-1的稀疏矩陣來代表原文本:

這種方法簡單暴力,直接根據文本中的單詞進行one-hot-encoding,但是數據量一但大了,這個單句話的one-hot-encoding結果會異常的長,而且沒辦法得到詞與詞之間的關係。

第二種是基於神經網絡的方法,常見的比如word2vec,YouTubeNet:

這種方法(這邊以CBOW爲例子)都是初始一個固定長度的隨機向量作爲每個單詞的向量,制定一個目標詞的向量,以上下文詞向量的sum結果作爲input進行前向傳遞,使得傳遞的結果和目標詞向量儘可能一致,以修正初始的隨機向量。

換句話說,就是剛開始,我隨意定義生成一個vector代表一個詞,然後通過上下文的聯繫去修正這個隨機的vector。好處就是我們可以得到詞與詞之間的聯繫,而且單個詞的表示不復雜,壞處就是需要大量的訓練樣本,畢竟涉及到了神經網絡。

最近,我們突然發現了第三種方法,GolVe向量化。它也是開始的時候隨機一個vector作爲單詞的表示,但是它不利用神經網絡去修正,而是利用了一個自己構造的損失函數:

通過我們已有的文章內容,去是的這個損失函數最小,這就變成了一個機器學習的方法了,相比較暴力的前饋傳遞,這也高快速和高效的多。同時,它還兼具了word2vec最後結果裏面vector方法的優點,得到詞與詞之間的聯繫,而且單個詞的表示不復雜。

這邊就不展開GolVe算法的細節了,後面有空和大家補充,這個算法的構造非常巧妙,值得大家借鑑一下。

文本分類

剛纔開門見山的聊了蠻久向量化,看起來和文本分類沒什麼關係,確實在通常意義上來講,我們的最簡單最常用的方法並不是向量化的方法,比如通過樸素貝葉斯,N-Grams這些方法來做分類識別。

tfidf+N-grams

1、其實很簡單,首先對語料庫進行切詞,維護自己的詞典,做高頻詞的人工複審,將無意詞進行stop_words歸總。

對公司內部信息進行了一下處理,主要看分佈趨勢

可以看到,高頻詞其實是非常非常少的,而且如果你真的去做了,你就會發現,"了"、“的”、“啊”這種語氣詞,和一些你公司相關的領域詞彙會非常靠前,這些詞作爲stop_words會有效的降低訓練成本、提高模型效果。

2、進行tf-idf,將詞進行重賦權,字詞的重要性隨着它在文件中出現的次數成正比增加,但同時會隨着它在語料庫中出現的頻率成反比下降,有效的將向量化中的one hot encoding結果進行了修正。但是依然存在問題:在TFIDF算法中並沒有體現出單詞的位置信息。

1# sublinear_tf:replace tf with 1 + log(tf)
2# max_df:用來剔出高於詞頻0.5的詞
3# token_pattern:(?u)\b\w+\b是爲了匹配出長度爲1及以上的詞,默認的至少需要詞長度爲2
4# ngram_range:這邊我做了3-grams處理,如果只想樸素計算的話(1,1)即可
5# max_features:隨着我做了各種寬鬆的條件,最後生成的詞維度會異常大,這邊限制了前3萬
6vectorizer = TfidfVectorizer(stop_words=stpwrdlst, sublinear_tf=True, max_df=0.5, token_pattern=r"(?u)\b\w+\b",ngram_range=(1, 3), max_features=30000)

不得不說,python處理機器學習,深度學習的便捷程度是異常的高。

3、在經過TfidfVectorizer處理之後的結果是以稀疏矩陣的形式來存的,如果想看內容的話,可以用todense()轉化爲matrix來看。接下來,用貝葉斯來訓練剛纔得到的矩陣結果就可以了。

1mnb_tri = MultinomialNB(alpha=0.001)
2mnb_tri.fit(tri_train_set.tdm, tri_train_set.label)

這種方法是上面方法的升級版本,我們先看下架構:

對公司內部信息進行了一下處理,主要看算法架構

其實主要差異在於右側的算法模型詳細部分,我們做了一個由3-grams到3-grams+naive-bayes+lr的擴充,提升精度。

在模型的過程中,上面的第一步,都是一樣的,在第二、三步有所差異:

2、在第二步中,我們除了要構造出一個3-grams的sparse matrix也需要構造出一個樸素的sparse matrix

1# 樸素結果
2vectorizerby = TfidfVectorizer(stop_words=stpwrdlst, token_pattern=r"(?u)\b\w+\b", max_df=0.5, sublinear_tf=True,ngram_range=(1, 1), max_features=100000)

3、不僅僅用bayes進行一次分類,而是根據3-grams和樸素情況下的sparse matrix進行預測,再用logistics regression來合併兩個的結果做個stack進行0-1壓縮。

1# 構造出一個3-grams的sparse matrix也需要構造出一個樸素的sparse matrix
2mnb_tri = MultinomialNB(alpha=0.001)
3mnb_tri.fit(tri_train_set.tdm, tri_train_set.label)
4mnb_by = MultinomialNB(alpha=0.001)
5mnb_by.fit(by_train_set.tdm, by_train_set.label)
1# 加bias,cv選擇最優正則結果,lbfgs配合l2正則
2lr = LogisticRegressionCV(multi_class="ovr", fit_intercept=True, Cs=np.logspace(-2, 2, 20), cv=2, penalty="l2",solver="lbfgs", tol=0.01)
3re = lr.fit(adv_data[['f1', 'f2']], adv_data['rep_label'])

總結一下上面兩種方法,我覺得是入門快,效果也不錯的小練手,也是完全可以作爲我們開始一個項目的時候,用來做baseline的方法,主要是快啊~/斜眼笑

GolVe+Ir

因爲我目前的帶標籤數據比較少,所以之前一直沒有敢用word2vec去向量化作死,但是GolVe不存在這個問題啊,我就美滋滋的進行了一波。

首先,先講下GolVe的使用:

  • https://github.com/stanfordnlp/GloVe 在最大的代碼抄襲網站下載(git clone)坦福大佬的代碼,友情提醒,不要作死自己看了理論就覺得自己會寫,自己搞個GloVe。(別問我是怎麼知道的)
  • cd到對應目錄下,vim demo.sh這個文件
 1#!/bin/bash
 2set -e
 3
 4# Makes programs, downloads sample data, trains a GloVe model, and then evaluates it.
 5# One optional argument can specify the language used for eval script: matlab, octave or [default] python
 6
 7# 請把make這邊註釋掉,這個是讓你去下個demo,我們直接改成自己的數據
 8# make
 9# if [ ! -e text8 ]; then
10#   if hash wget 2>/dev/null; then
11#     wget http://mattmahoney.net/dc/text8.zip
12#   else
13#     curl -O http://mattmahoney.net/dc/text8.zip
14#   fi
15#   unzip text8.zip
16#   rm text8.zip
17# fi
18
19# CORPUS需要對應自己的欲訓練的文檔
20CORPUS=content.txt
21VOCAB_FILE=vocab.txt
22COOCCURRENCE_FILE=cooccurrence.bin
23COOCCURRENCE_SHUF_FILE=cooccurrence.shuf.bin
24BUILDDIR=build
25SAVE_FILE=vectors
26VERBOSE=2
27MEMORY=4.0
28# 單詞至少出現幾次
29VOCAB_MIN_COUNT=3
30# 向量長度
31VECTOR_SIZE=128
32# 迭代次數
33MAX_ITER=30
34# 窗口長度
35WINDOW_SIZE=15
36BINARY=2
37NUM_THREADS=8
38X_MAX=10
39
40echo
41echo "$ $BUILDDIR/vocab_count -min-count $VOCAB_MIN_COUNT -verbose $VERBOSE < $CORPUS > $VOCAB_FILE"
42$BUILDDIR/vocab_count -min-count $VOCAB_MIN_COUNT -verbose $VERBOSE < $CORPUS > $VOCAB_FILE
43echo "$ $BUILDDIR/cooccur -memory $MEMORY -vocab-file $VOCAB_FILE -verbose $VERBOSE -window-size $WINDOW_SIZE < $CORPUS > $COOCCURRENCE_FILE"
44$BUILDDIR/cooccur -memory $MEMORY -vocab-file $VOCAB_FILE -verbose $VERBOSE -window-size $WINDOW_SIZE < $CORPUS > $COOCCURRENCE_FILE
45echo "$ $BUILDDIR/shuffle -memory $MEMORY -verbose $VERBOSE < $COOCCURRENCE_FILE > $COOCCURRENCE_SHUF_FILE"
46$BUILDDIR/shuffle -memory $MEMORY -verbose $VERBOSE < $COOCCURRENCE_FILE > $COOCCURRENCE_SHUF_FILE
47echo "$ $BUILDDIR/glove -save-file $SAVE_FILE -threads $NUM_THREADS -input-file $COOCCURRENCE_SHUF_FILE -x-max $X_MAX -iter $MAX_ITER -vector-size $VECTOR_SIZE -binary $BINARY -vocab-file $VOCAB_FILE -verbose $VERBOSE"
48$BUILDDIR/glove -save-file $SAVE_FILE -threads $NUM_THREADS -input-file $COOCCURRENCE_SHUF_FILE -x-max $X_MAX -iter $MAX_ITER -vector-size $VECTOR_SIZE -binary $BINARY -vocab-file $VOCAB_FILE -verbose $VERBOSE
49if [ "$CORPUS" = 'text8' ]; then
50if [ "$1" = 'matlab' ]; then
51matlab -nodisplay -nodesktop -nojvm -nosplash < ./eval/matlab/read_and_evaluate.m 1>&2 
52elif [ "$1" = 'octave' ]; then
53octave < ./eval/octave/read_and_evaluate_octave.m 1>&2
54else
55echo "$ python eval/python/evaluate.py"
56python eval/python/evaluate.py
57  fi
58fi

這邊多說一下,CORPUS=content.txt這邊content.txt裏面的格式需要按照空格爲分隔符進行存儲,我之前一直以爲是\t。

  • 直接sh demo.sh,你會得到vectors.txt,這個裏面就對應每個詞的向量表示
1天氣 -0.754142 0.386905 -1.200074 -0.587121 0.758316 0.373824 0.342211 -1.275982 -0.300846 0.374902 -0.548544 0.595310 0.906426 0.029255 0.549932 -0.650563 -0.425185 1.689703 -1.063556 -0.790254 -1.191287 0.841529 1.080641 -0.082830 1.062107 -0.667727 0.573955 -0.604460 -0.601102 0.615299 -0.470923 0.039398 1.110345 1.071094 0.195431 -0.155259 -0.781432 0.457884 1.093532 -0.188207 -0.161646 0.246220 -0.346529 0.525458 0.617904 -0.328059 1.374414 1.020984 -0.959817 0.670894 1.091743 0.941185 0.902730 0.609815 0.752452 1.037880 -1.522382 0.085098 0.152759 -0.562690 -0.405502 0.299390 -1.143145 -0.183861 0.383053 -0.013507 0.421024 0.025664 -0.290757 -1.258696 0.913482 -0.967165 -0.131502 -0.324543 -0.385994 0.711393 1.870067 1.349140 -0.541325 -1.060084 0.078870 0.773146 0.358453 0.610744 0.407547 -0.552853 1.663435 0.120006 0.534927 0.219279 0.682160 -0.631311 1.071941 -0.340337 -0.503272 0.150010 1.347857 -1.024009 -0.181186 0.610240 -0.218312 -1.120266 -0.486539 0.264507 0.266192 0.347005 0.172728 0.613503 -0.131925 -0.727304 -0.504488 1.773406 -0.700505 -0.159963 -0.888025 -1.358476 0.540589 -0.243272 -0.236959 0.391855 -0.133703 -0.071120 1.050547 -1.087613 -0.467604 1.779341 -0.449409 0.949411
2好了 1.413075 -0.226177 -2.024229 -0.192003 0.628270 -1.227394 -1.054946 -0.900683 -1.958882 -0.133343 -1.014088 -0.434961 0.026207 -0.066139 0.608682 -0.362021 0.314323 0.261955 -0.571414 1.738899 -1.013223 0.503853 -0.536511 -0.212048 0.611990 -0.627851 0.297657 -0.187690 -0.565871 -0.234922 -0.845875 -0.767733 0.032470 1.508012 -0.204894 -0.495031 -0.159262 0.181380 0.050582 -0.333469 0.454832 -2.091174 0.448453 0.940212 0.882077 -0.617093 0.616782 -0.993445 -0.385087 0.251711 0.259918 -0.222614 -0.595131 0.661472 0.194740 0.619222 -1.253610 -0.838179 0.781428 -0.396697 -0.530109 0.022801 -0.558296 -0.656034 0.842634 -0.105293 0.586823 -0.603681 -0.605727 -0.556468 0.924275 -0.299228 -1.121538 0.237787 0.498935 -0.045423 0.171536 -1.026385 -0.262225 0.390662 1.263240 0.352172 0.261121 0.915840 1.522183 -0.498536 2.046169 0.012683 -0.073264 -0.361662 0.759529 -0.713268 0.281747 -0.811104 -0.002061 -0.802508 0.520559 0.092275 -0.623098 0.199694 -0.134896 -1.390617 0.911266 -0.114067 1.274048 1.108440 -0.266002 1.066987 0.514556 0.144796 -0.606461 0.197114 0.340205 -0.400785 -0.957690 -0.327456 1.529557 -1.182615 0.431229 -0.084865 0.513266 -0.022768 -0.092925 -0.553804 -2.269741 -0.078390 1.376199 -1.163337
3隨意 0.410436 0.776917 -0.381131 0.969900 -0.804778 -0.785379 -0.887346 -1.463543 -1.574851 0.313285 0.685253 -0.918359 0.199073 -0.305374 -0.642721 0.098114 -0.723331 0.353159 0.042807 0.369208 -1.534930 -0.084871 0.020417 -0.384782 0.276833 -0.160028 1.107051 0.884343 -0.204381 -0.459738 -0.387128 0.125867 0.093569 1.192471 -0.473752 -0.314541 -1.029249 0.481447 1.358753 -1.688778 -0.113080 -0.401443 -0.958206 0.605638 1.083126 0.131617 0.092507 0.476506 0.801755 1.096883 -0.102036 0.461804 0.820297 -0.104053 -0.126638 0.957708 -0.722038 0.223686 0.583582 0.201246 -1.254708 0.770717 -1.271523 -0.584094 -1.142426 1.066567 0.071951 -0.182649 0.014365 -0.577141 0.037340 -0.166832 -0.247827 0.165994 1.143665 -0.258421 -0.335195 0.170218 -0.212838 0.013709 0.088847 0.663238 -0.597439 0.632847 0.370871 0.652707 0.306935 0.195127 -0.252443 0.588479 0.191633 -1.587564 0.564600 -0.306158 -0.648177 -0.488595 1.532795 -0.462473 -0.643878 1.292369 -0.051494 -1.032738 0.453587 0.411327 -0.469373 0.428398 -0.020839 0.307422 0.518331 -0.860913 -2.170098 -0.277532 -0.966210 0.615336 -0.924783 0.042679 1.289640 1.272992 1.367773 0.426600 -0.187254 -0.781009 1.331301 -0.088357 -1.113550 -0.262879 0.300137 0.437905
4..
  • 有了每個詞的向量,我們這邊採取了借鑑YoutubeNet網絡的想法:

舉個例子:存在一句話"我愛中國",“我”的向量是[0.3,0.2,0.3],"愛"的向量是[0.1,0.2,0.3],“中國”的向量是[0.6,0.6,0.4],那麼average後就是[0.5,0.5,0.5],然後這就類似一個特徵爲三的input。

這種方法的好處就是快捷,預處理的工作代價要小,隨着數據量的增多,模型的效果要更加的好,這邊給出一下業務數據對比:

experiment

date

intercepted_recall

3-grams

20180915

79.3%

3-grams

20180917

78.7%

3-grams+bayes+lr

20180915

83.4%

3-grams+bayes+lr

20180917

88.6%

gloVe+lr

20180915

93.1%

gloVe+lr

20180917

93.9%

原文鏈接:https://www.jianshu.com/p/92ae72d67e5e

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章