前言
仅记录学习过程,有问题欢迎讨论
one-hot 编码 i love u [1,2,3]
词向量训练目标:
如果两个词在文本出现,它的前后出现的词相似,则这两个词语义相似
cbow(基于窗口预测词)缺点
:输出层是vocab_size 会很大
收敛速度会很慢
skipGram --用中间词预测两侧词
哈夫曼树:
用词频来构造树,词频最大,在树的层级越小
对词向量输出层级过大的优化
Glove 词向量:
按照词来编写关于前后语义关系的矩阵---共现矩阵
词向量存在的问题:
1)词向量是"静态"的。每个词使用固定向量,没有考虑前后文
2)一词多义的情况。西瓜 - 苹果 - 华为
3)影响效果的因素非常多
维度选择、随机初始化、skip-gram/cbow/glove、分词质量、词频截断、未登录词、窗口大小、迭代轮数、停止条件、语料质量等
4)没有好的直接评价指标。常需要用下游任务来评价
句向量:
对于所有的词加和求平均 得到文本向量 计算其相似性和聚类
Kmeans
KMeans一些使用技巧:
先设定较多的聚类类别
聚类结束后计算类内平均距离
排序后,舍弃类内平均距离较长的类别
总结:
1.质变:将离散的字符转化为连续的数值
2.通过向量的相似度代表语义的相似度
3.词向量的训练基于很多不完全正确的假设,但是据此训练的词向量是有意义的
4.使用无标注的文本的一种好方法
代码
Demo1:使用gensim
pip install gensim
寻找词之间的相似性
java
"""
实现一个 TFIDF
"""
import gensim
import jieba
def gensim_train(corpus, dim):
model = gensim.models.Word2Vec(corpus, # 用于训练的语料数据
vector_size=dim, # 是指特征向量的维度,默认为100。
window=5, # 一个句子中当前单词和被预测单词的最大距离。
min_count=1, # 可以对字典做截断. 词频少于min_count次数的单词会被丢弃掉, 默认值为5。
sg=1)
model.save("word2vec.w2v")
return model
def main():
sentences = []
with open("D:\\NLP\\test\\week5\\corpus.txt",encoding="utf8") as f:
for line in f:
sentences.append(jieba.lcut(line))
model = gensim_train(sentences, 100)
return model
if __name__ == '__main__':
# model = main()
# 加载模型
model = gensim.models.Word2Vec.load("word2vec.w2v")
# print(model.wv.most_similar(positive=["男人", "母亲"], negative=["女人"]))
while True: #找相似
string = input("input:")
try:
print(model.wv.most_similar(string))
except KeyError:
print("输入词不存在")
kmeans Demo
找出平均距离最大的类内中心点,然后去除该中心点
python
#!/usr/bin/env python3
# coding: utf-8
# 基于训练好的词向量模型进行聚类
# 聚类采用Kmeans算法
import math
from collections import defaultdict
import gensim
import jieba
import numpy as np
# 基于训练好的词向量模型进行聚类
# 聚类采用Kmeans算法
from gensim.models import Word2Vec
from gensim.models import Word2Vec
from sklearn.cluster import KMeans
# 输入模型文件路径
# 加载训练好的模型
def load_word2vec_model(path):
model = Word2Vec.load(path)
return model
def load_sentence(path):
sentences = set()
with open(path, encoding="utf8") as f:
for line in f:
sentence = line.strip()
sentences.add(" ".join(jieba.cut(sentence)))
print("获取句子数量:", len(sentences))
return sentences
# 将文本向量化
def sentences_to_vectors(sentences, model):
vectors = []
for sentence in sentences:
words = sentence.split() # sentence是分好词的,空格分开
vector = np.zeros(model.vector_size)
# 所有词的向量相加求平均,作为句子向量
for word in words:
try:
vector += model.wv[word]
except KeyError:
# 部分词在训练中未出现,用全0向量代替
vector += np.zeros(model.vector_size)
vectors.append(vector / len(words))
return np.array(vectors)
# vec1 = 类别
# vec2 = 该类下的数据
def calculate_distant(vec1, vec2):
return np.sqrt(sum(np.power(vec1 - vec2, 2)))
def main():
model = gensim.models.Word2Vec.load("D:\\NLP\\test\\dayPractice\\word2vec.w2v") # 加载词向量模型
sentences = load_sentence("titles.txt") # 加载所有标题
vectors = sentences_to_vectors(sentences, model) # 将所有标题向量化
n_clusters = int(math.sqrt(len(sentences))) # 指定聚类数量
print("指定聚类数量:", n_clusters)
kmeans = KMeans(n_clusters) # 定义一个kmeans计算类
kmeans.fit(vectors) # 进行聚类计算
sentence_label_dict = defaultdict(list)
# for list1 in kmeans.cluster_centers_:
# print(list1)
center_list = defaultdict(list)
sentence_index_label_dict = defaultdict(list)
index = 0
# 取出kmeans的聚点,丢弃掉类内平均距离最长的那个聚点
for sentence, label in zip(sentences, kmeans.labels_): # 取出句子和标签
sentence_label_dict[label].append(sentence) # 同标签的放到一起(分好 一簇的)
sentence_index_label_dict[label].append(index) # 同标签的放到一起(记录的是句子的index)
index += 1
# 记录该组的中心点向量值
for index, center in enumerate(kmeans.cluster_centers_):
# 记录该组的中心点向量值
center_list[index].append(center)
distant_list = defaultdict(list)
for label, index_list in sentence_index_label_dict.items():
# 计算本组所有点到中心点的距离和
temp_i = []
for i in index_list:
temp_i.append(calculate_distant(center_list.get(label), vectors[i]))
# 记录当前组的组内平均距离
distant_list[label].append(np.mean(temp_i))
# 丢弃距离最大的那组
drop_label = max(distant_list)
del sentence_label_dict[drop_label]
for label, sentences in sentence_label_dict.items():
print("cluster %s :" % label)
for i in range(min(10, len(sentences))): # 随便打印几个,太多了看不过来
print(sentences[i].replace(" ", ""))
print("---------")
if __name__ == "__main__":
main()