NLP初學-文本表示

一、詞袋模型(BOW)

詞袋模型是一種簡單常用的模型,在該模型中,我們可以把文本看做是一系列詞的集合,我們用袋子來把他們裝起來就叫做詞袋,這麼說可能有些抽象,用一個例子來表示一下:

有一段文本:"it is a beautiful day today"

進行分詞處理:it/is/a/beautiful/day/today

得到詞袋:("it","is","a","beautiful","day","today")

但是我們得到的詞袋要交給計算機處理,計算機並不能很好的識別英文,只能識別數字,那麼我們給每一個詞添加一個索引去解決這個問題:

詞袋索:(0,1,2,3,4,5)

對於需要考慮詞頻的詞袋模型我們可以定義成用一個數字來表示索引一個數字來表示詞頻的形式:[(0,2),(1,2),(2,2)......]

上例是詞袋模型的一種表示方法, 下面舉另外一個例子來表示一下:

給出兩個文本:

     1:Bob likes to play basketball, Jim likes too.

     2:Bob also likes to play football games.

我們可以構造出一個詞典:

 {1:”Bob”, 2. “like”, 3. “to”, 4. “play”, 5. “basketball”, 6. “also”, 7. “football”, 8. “games”, 9. “Jim”, 10. “too”}。

上面的詞典中包含了10個單詞,對於每個單詞都有一個唯一的索引,那麼對於兩個文本我們有如下的詞袋錶示方法:

     1:[1, 2, 1, 1, 1, 0, 0, 0, 1, 1]

     2:[1, 1, 1, 1 ,0, 1, 1, 1, 0, 0]

詞袋模型適用的數據類型:離散,高維,稀疏

詞袋模型存在的問題:

1、維度災難,如果一個例子詞典中包含10000個單詞,那麼每個文本需要用10000維的向量表示。

2、無法保留詞序信息

3、存在語義鴻溝的問題
代碼示例

from sklearn.feature_extraction.text import CountVectorizer
# list of text documents
text = ["The quick brown fox jumped over the lazy dog."]
# create the transform
vectorizer = CountVectorizer()
# tokenize and build vocab
vectorizer.fit(text)
# summarize
print(vectorizer.vocabulary_)
# encode document
vector = vectorizer.transform(text)
# summarize encoded vector
print(vector.shape)
print(type(vector))
print(vector.toarray())

二、one-hot(獨熱碼)

one-hot是表示一項屬性的特徵向量,向量中只有一個特徵是不爲0的,其他的特徵都爲0(簡單的來說就是將一個bit的位置填1,其他位置都填0),比如機器學習中對於離散型的分類數據,需要對其進行數字化,此時便可以使用獨熱碼來表示,舉例表示一下:

對於一個特徵是離散值的情況:

性別:{男,女,其他}

可以看到上面的性別特徵有三個不同的分類值,也就意味着我們需要三個bit的值來表示這些類別,此時可以用獨熱碼錶示爲:

男:{100},女:{010},其他:{001}

對於多個特徵時:

性別:{男,女,其他}

年級:{一年級,二年級,三年級,四年級}

那麼對於一年級的男生編碼既可以爲:{1001000}(前面的100表示男生,後面的1000表示一年級)

from sklearn import preprocessing
 
ont_hot = preprocessing.OneHotEncoder()
data = [[0, 1, 2], [0, 0, 1], [1, 0, 0], [1, 1, 3]]
ont_hot.fit(data)
print(ont_hot.transform([[1, 0, 3]]).toarray())


三、word2vec

word2vec技術是一種爲了利用神經網絡從大量無標註的文本中提取有用信息而產生的向量。

上文中我們提到了one-hot編碼,但是獨熱碼中只有一個bit的數值爲1其餘都爲0,對於需要編碼很多類別的情況容易產生維度災難,那麼我們能不能把維度變低呢,下面我們就來說一下word2vec。

word2vec本質上是一種簡單的神經網絡,它分爲兩種訓練模型(CBOW和Skip-gram):

word2vec模型的主要構成如下:

該模型的輸入是one-hot編碼,Hidden Layer是線性單元(沒有激活函數),Output的使用的是softmax迴歸(輸出輸入詞的鄰近詞的概率分佈),維度和input相同,模型訓練後輸入層和隱藏層之間權重即爲我們要獲取的詞向量。

CBOW模型是根據中心詞W(t)周圍的詞來預測中心詞。

Skip-gram模型是根據中心詞W(t)來預測周圍的詞。

示例代碼:

process_wiki.py

from __future__ import print_function

import logging
import os.path
import six
import sys

from gensim.corpora import WikiCorpus

if __name__ == '__main__':
    program = os.path.basename(sys.argv[0])
    logger = logging.getLogger(program)

    logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
    logging.root.setLevel(level=logging.INFO)
    logger.info("running %s" % ' '.join(sys.argv))

    # check and process input arguments
    if len(sys.argv) != 3:
        print("Using: python process_wiki.py enwiki.xxx.xml.bz2 wiki.en.text")
        sys.exit(1)
    inp, outp = sys.argv[1:3]
    space = " "
    i = 0

    output = open(outp, 'w')
    wiki = WikiCorpus(inp, lemmatize=False, dictionary={})
    for text in wiki.get_texts():
        if six.PY3:
            output.write(bytes(' '.join(text), 'utf-8').decode('utf-8') + '\n')
        #   ###another method###
        #    output.write(
        #            space.join(map(lambda x:x.decode("utf-8"), text)) + '\n')
        else:
            output.write(space.join(text) + "\n")
        i = i + 1
        if i % 10000 == 0:
            logger.info("Saved " + str(i) + " articles")

    output.close()
    logger.info("Finished Saved " + str(i) + " articles")

train_word2vec_model.py

from __future__ import print_function

import logging
import os
import sys
import multiprocessing

from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence

if __name__ == '__main__':
    program = os.path.basename(sys.argv[0])
    logger = logging.getLogger(program)

    logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
    logging.root.setLevel(level=logging.INFO)
    logger.info("running %s" % ' '.join(sys.argv))

    # check and process input arguments
    if len(sys.argv) < 4:
        print("Useing: python train_word2vec_model.py input_text "
              "output_gensim_model output_word_vector")
        sys.exit(1)
    inp, outp1, outp2 = sys.argv[1:4]

    model = Word2Vec(LineSentence(inp), size=200, window=5, min_count=5,
                     workers=multiprocessing.cpu_count())

    model.save(outp1)
    model.wv.save_word2vec_format(outp2, binary=False)

model.py

import gensim
model = gensim.models.Word2Vec.load("wiki.en.text.model")

print(model.most_similar("man"))

數據:enwiki-latest-pages-articles.xml.bz2(自行百度下載,大概16G)

 

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