一、词袋模型
维度=|词典|; 稀疏向量
假设词典里有7个单词【我们,去,爬山,今天,你们,昨天,运动】
每个单词的表示:
我们:[1,0,0,0,0,0,0]
爬山:[0,0,1,0,0,0,0]
运动:[0,0,1,0,0,0,1]
句子的表示:
我们今天去爬山:[1,1,1,1,0,0,0]
你们昨天运动:[0,0,0,0,1,1,1]
怎么表示句子的相关性?
欧式距离计算:d=|s1-s2| 只关注距离没考虑方向 , 值越高句子相似度越低
余弦相似度计算:d = (s1*s2)/|s1|*|s2| 值越高句子相似度越高
TFIDF
如何刻画每个单词的重要性,上图只考虑了词的频率,把每个单词的重要性考虑进来。TFIDF,考虑了频率和重要性。
corpus = ['He is going from Beijing to Shanghai.', 'He denied my request, but he actually lied.', 'Mike lost the phone, and phone was in the car']#方法1只考虑词频from sklearn.feature_extraction.text import CountVectorizervectorizer = CountVectorizer()X=vectorizer.fit_transform(corpus)print(X.toarray())#方法2 考虑词频和重要性TFIDFfrom sklearn.feature_extraction.text import TfidfVectorizervectorizer = TfidfVectorizer()X=vectorizer.fit_transform(corpus)print(X.toarray())
二、Word2Vec词向量表示
从词袋模型到分布式表示,通过深度学习模型Word2Vec(SkipGram, Glove, Cbow, Gaussion Embedding, Hyperbolic Embedding)将词表示成向量(计算每个单词的词向量),模式的输入是我们的语料库。
有了词向量后,句子向量的求法有很多:1.求平均average 2.考虑时序模型LSTM RNN(可以计算整个句子的向量)
提前准备语料库,假设是金融相关的语料库,比如研报;使用word2vec开源工具
python word2vec.py -train wiki_sample.txt -cbow 0 -negative 10 -dim 20 -window 5 -min-count 5
三、命名实体识别
按照类型标记每一个名词。比如“张三出生于北京,北京大学毕业后去华为任职”。对于文章里面的话做进一步的分类,分类的结果可以是人名、地名、组织或时间。
命名实体识别对于知识图谱的构建十分重要,聊天机器人也十分重要。
使用随机森林预测实体类别
1 from sklearn.preprocessing import LabelEncoder 2 from sklearn.model_selection import cross_val_predict 3 from sklearn.metrics import classification_report 4 #列名:Sentence# word pos Tag 5 # Sentence1 Throunds NNS O 6 # Sentence1 of IN O 7 8 data = pd.read_csv('ner_dataset.csv') 9 #读取每句话10 def get_sentences(data):11 agg_func = lambda s: [(w,p,t) for w, p, t in12 zip(s["word"].values.tolist(), s["pos"].values.tolist(),13 s["Tag"].values.tolist())]14 sentence_grouped = data.group("sentence#").apply(agg_func)15 return [s for s in sentence_grouped]16 sentences = get_sentences(data)17 #特征工程18 out = []19 y = []20 mv_tagger = MajorityVoting()21 tag_encoder = LabelEncoder()22 pos_encoder = LabelEncoder()23 words = data['word'].values.tolist()24 tags = data['Tag'].values.tolist()25 mv_tagger.fit(words, tags)26 tag_encoder.fit(tags)27 pos_encoder.fit(pos)28 for sentence in sentences:29 # w:单词,p:词性, t:NER标签30 for i in range(len(sentences)):31 w, p, t = sentences[i][0], sentences[i][1], sentences[i][2]32 # 如果不是句子中的最后一个单词,则可以提取出上下文特征33 if i< len(sentence)-1:34 mem_tag_r = tag_encoder.transform(mv_tagger.predict([sentence[i+1][0]])[0])[0]35 true_pos_r = pos_encoder.transform(sentence[i+1][1])[0]36 else:37 mem_tag_r = tag_encoder.transform(['O'])[0]38 true_tag_r = pos_encoder.transform(['.'])[0]39 # 如果不是句子中的第一个单词,则可以提取上文的特征40 if i>0:41 mem_tag_r = tag_encoder.transform(mv_tagger.predict([sentence[i-1][0]])[0])[0]42 true_pos_r = pos_encoder.transform(sentence[i-1][1])[0]43 else:44 mem_tag_r = tag_encoder.transform(['O'])[0]45 true_tag_r = pos_encoder.transform(['.'])[0]46 out.append(np.array([w.istitle(), w.islower(), w.isupper(), len(w), w.isdigit(), w.isalpha(),47 tag_encoder.transform(mv_tagger.predict([w]))[0],48 pos_encoder.transoform([p])[0],49 mem_tag_r, true_pos_r, mem_tag_r, true_tag_r]))50 y.append(t)51 pred = cross_val_predict(RandomForestClassifier(n_estimator=20), X=out,y=y, cv=5)52 report = classification_report(y_pred=pred, y_true=tags)
使用CRF预测实体类别
HM是当前词只受前一个词的影响,CRF是当前词会受一整句话有关系,考虑时序。但是参数轨迹和推断很难,无向图计算量上比有向图难很多。
def word2feature(sent, i): """ :param sent: input sentence :param i:index of word """ word = sent[i][0] postag = sent[i][1] feature = { 'bias':1.0, 'word.lower()':word.lower(), 'word[-3:]':word[-3:], 'word.isupper()':word.isupper(), 'word.istitle()':word.istitle(), 'word.isdigit()':word.isdigit(), 'postag':postag, 'postag[:2]':postag[:2], } #提取前缀特征 if i>0: word1 = sent[i-1][0] postag1 = sent[i-1][1] feature.update({ '-1:word.lower()':word1.lower(), '-1:word.istitle()':word1.istitle(), '-1:word.isupper()': word1.isupper(), '-1:postag':postag1, '-1:postag[:2]':postag1[:2] }) else: feature['BOS']=True #提取下文特征 if i