知识点

"""
1) from gensim.model import Word2Vec
  import jieba 2) opencc :将繁体字转换为简体字 转换命令:opencc -i texts.txt -o test.txt -c t2s.json 3) 自然语言处理: 1、拼写检查、关键字检索 2、文本挖掘 3、文本分类 (二分类) 4、机器翻译 5、客服系统 6、复杂对话系统 4) p(S)=p(w1,w2,w3,w4,w5,…,wn) =p(w1)p(w2|w1)p(w3|w1,w2)...p(wn|w1,w2,...,wn-1) 计算方式:p(wi|w1,w2,...,wi-1) = p(w1,w2,...,wi-1,wi) / p(w1,w2,...,wi-1) 5) 语言模型问题:(1)数据过于稀疏 (2)参数空间太大
   针对上述两个问题两种优化方法(N-gram模型): 1)假设下一个词的出现依赖它前面的一个词: p(S)=p(w1)p(w2|w1)p(w3|w1,w2)...p(wn|w1,w2,...,wn-1)=p(w1)p(w2|w1)p(w3|w2)...p(wn|wn-1) 2)假设下一个词的出现依赖它前面的两个词: p(S)=p(w1)p(w2|w1)p(w3|w1,w2)...p(wn|w1,w2,...,wn-1)=p(w1)p(w2|w1)p(w3|w1,w2)...p(wn|wn-1,wn-2)   模型参数个数跟语料库字典数和N相关,即 字典数^N个参数  
6) word2vec过程: 1、数据获取 2、分词 3、gensim的word2vec建模 4、model.similarity()进行预测

7)word2vec()参数

    # - sentences:可以是一个list
    # - sg: 用于设置训练算法,默认为0,对应CBOW算法;sg=1则采用skip-gram算法。
    # - size:是指特征向量的维度,默认为100。大的size需要更多的训练数据,但是效果会更好. 推荐值为几十到几百。
    # - window:表示当前词与预测词在一个句子中的最大距离是多少
    # - alpha: 是学习速率
    # - seed:用于随机数发生器。与初始化词向量有关。
    # - min_count: 可以对字典做截断. 词频少于min_count次数的单词会被丢弃掉, 默认值为5
    # - max_vocab_size: 设置词向量构建期间的RAM限制。如果所有独立单词个数超过这个,则就消除掉其中最不频繁的一个。每一千万个单词需要大约1GB的RAM。设置成None则没有限制。
    # - workers参数控制训练的并行数。
    # - hs: 如果为1则会采用hierarchica·softmax技巧。如果设置为0(defau·t),则negative sampling会被使用。
    # - negative: 如果>0,则会采用negativesamp·ing,用于设置多少个noise words
    # - iter: 迭代次数,默认为5

"""

词向量

"""
词向量解决方案:
    1、one-hot编码
        缺点:这种方案浪费存储空间还是次要的,更重要的是词与词(向量与向量)之间没有相关性,计算机完全无法进行哪怕一丁点的理解和处理
    2、基于奇异值分解(SVD)的方法
        步骤:a)第一步是通过大量已有文档统计形成词空间矩阵X,有两种办法。
                一种是统计出某篇文档中各个词出现的次数,假设词的数目是W、文档篇数是M,则此时X的维度是W*M;
                第二种方法是针对某个特定词,统计其前后文中其它词的出现频次,从而形成W*W的X矩阵。
              b)第二步是针对X矩阵进行SVD分解,得到特征值,根据需要截取前k个特征值及对应的前k个特征向量,
                那么前k个特征向量构成的矩阵维度是W*k,这就构成了所有W个词的k维表示向量
        缺点:
            1、需要维护一个极大的词空间稀疏矩阵X,而且随着新词的出现还会经常发生变化;
            2、SVD运算量大,而且每增减一个词或文档之后,都需要重新计算
    3、构建一个word2vec模型:通过大量文档迭代学习其中的参数及已有词的编码结果,这样每新来一篇文档都不用修改已有模型,只需要再次迭代计算参数和词向量即可
            举例:我爱python和java
            a)CBOW算法: 输入:我爱, 目标值:python和java
                   CBOW算法使用上下文窗口内词向量作为输入,将这些向量求和(或取均值)后,求得与输出词空间的相关性分布,
                   进而使用softmax函数得到在整个输出词空间上的命中概率,与目标词one-hot编码的交叉熵即为loss值,
                   通过loss针对输入和输出词向量的梯度,即可使用梯度下降(gradient descent)法得到一次针对输入和输出词向量的迭代调整。

            b)Skip-Gram算法: 输入:python和java, 目标值:我爱
                    Skip-Gram算法使用目标词向量作为输入,求得其与输出词空间的相关性分布,
                    进而使用softmax函数得到在整个输出词空间上的命中概率,与one-hot编码的上下文词逐一计算交叉熵,
                    求和后即为loss值,通过loss针对输入和输出词向量的梯度,
                    即可使用梯度下降(gradient descent)法得到一次针对输入和输出词向量的迭代调整
"""

1、wiki词库处理----.bz2格式转为text格式

 

#!/usr/bin/env python
# -*- coding: utf-8  -*-
#将xml的wiki数据转换为text格式

import logging
import os.path
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))

    if len(sys.argv) < 3:
        #print globals()['__doc__'] % locals()
        sys.exit(1)

    inp, outp = sys.argv[1:3]
    space = " "
    i = 0

    output = open(outp, 'w')
    wiki =WikiCorpus(inp, lemmatize=False, dictionary=[])#gensim里的维基百科处理类WikiCorpus
    for text in wiki.get_texts():#通过get_texts将维基里的每篇文章转换位1行text文本,并且去掉了标点符号等内容
        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.")
#python bz2_to_text.py zhwiki-latest-pages-articles.xml.bz2 wiki.zh_ywj.txt
#opencc -i wiki_texts.txt -o test.txt -c t2s.json 将繁体字转为简体字

 

2、对简体语料库进行jieba分词

import jieba
import jieba.analyse
import jieba.posseg as pseg
import codecs,sys
def cut_words(sentence):
    #print sentence
    return " ".join(jieba.cut(sentence)).encode('utf-8')
f=codecs.open('wiki.zh.jian.text','r',encoding="utf8")
target = codecs.open("zh.jian.wiki.seg-1.3g.txt", 'w',encoding="utf8")
print ('open files')
line_num=1
line = f.readline()
while line:
    print('---- processing ', line_num, ' article----------------')
    line_seg = " ".join(jieba.cut(line))
    target.writelines(line_seg)
    line_num = line_num + 1
    line = f.readline()
f.close()
target.close()
exit()
while line:
    curr = []
    for oneline in line:
        #print(oneline)
        curr.append(oneline)
    after_cut = map(cut_words, curr)
    target.writelines(after_cut)
    print ('saved',line_num,'articles')
    exit()
    line = f.readline1()
f.close()
target.close()

# python Testjieba.py

3、word2vec建模

import logging
import os.path
import sys
import multiprocessing
from gensim.corpora import WikiCorpus
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 (globals()['__doc__'] % locals())
        sys.exit(1)
    inp, outp1, outp2 = sys.argv[1:4]
    model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5, workers=multiprocessing.cpu_count())
    model.save(outp1)
    model.model.wv.save_word2vec_format(outp2, binary=False)
#python word2vec_model.py zh.jian.wiki.seg.txt wiki.zh.text.model wiki.zh.text.vector
#opencc -i wiki_texts.txt -o test.txt -c t2s.json

4、加载模型,预测

from gensim.models import Word2Vec

en_wiki_word2vec_model = Word2Vec.load('wiki.zh.text.model')

testwords = ['苹果','数学','学术','白痴','篮球']
for i in range(5):
    res = en_wiki_word2vec_model.most_similar(testwords[i])
    print (testwords[i])
    print (res)