"Это 6-й день моего участия в ноябрьском испытании обновлений, ознакомьтесь с подробностями события:Вызов последнего обновления 2021 г."
Справочные примечания:Технология предварительной обработки Nuggets-NLP
Автор расширяет содержание части извлечения признаков (Feature Extraction) в соответствии с ее структурой и собственным накоплением знаний.
1. Извлечение признаков
Чтобы лучше обучить модель, нам нужно преобразовать исходные функции текста в конкретные функции.Существует два основных способа преобразования: статистика и встраивание.
Оригинальные функции: должны быть преобразованы людьми или машинами, например: текст, изображения.
Конкретные особенности: он был организован и проанализирован людьми и может использоваться напрямую, например, важность и размер объектов.
1.1 Статистика
- Частота слов относится к частоте данного слова в файле, которую необходимо нормализовать, чтобы избежать смещения в сторону длинных текстов.
- Обратная частота файлов, мера общей важности слова, деленная на общее количество файлов на количество файлов, содержащих это слово.
Затем каждое слово получит значение TF-IDF для измерения его важности Формула расчета выглядит следующим образом:
Справочные материалы:sklearn-TfidfVectorizer делает это понятным
1) В следующем коде используется алгоритм TFIDF sklearn для извлечения признаков.
# 使用 sklearn的TFIDF算法进行特征提取
import jieba
from sklearn.feature_extraction.text import TfidfTransformer,TfidfVectorizer,CountVectorizer
corpus = ["词频,是指某一个给定的词在该文件中出现的频率,需要进行归一化,避免偏向长文本",
"逆向文件频率,是一个词普遍重要性的度量,由总文件数目除以包含该词的文件数目"]
corpus_list = []
for corpu in corpus:
corpus_list.append(" ".join(jieba.cut_for_search(corpu)))
print("\n语料大小:{}\n{}".format(len(corpus_list),corpus_list))
vectorizer = TfidfVectorizer(use_idf=True, smooth_idf=True, norm=None)
tfidf = vectorizer.fit_transform(corpus_list)
weight = tfidf.toarray()
vocab = vectorizer.get_feature_names()
print("\n词汇表大小:{}\n{}".format(len(vocab),vocab))
print("\n权重形状:{}\n{}".format(weight.shape,weight))
2) Используйте алгоритм TFIDF в сегментации слов jieba для извлечения ключевых слов.
# jieba分词中 基于TFIDF的关键词提取
import jieba
import jieba.analyse
sentences = ['中华蜜蜂原产于中国,是中国的土著蜂,适应中国各地的气候和蜜源条件,适于定地饲养且稳产,尤其是在南方山区,有着其他蜂种不可替代的地位。',
'东方蜜蜂原产地在东方、简称东蜂,是蜜蜂属中型体中等的一个品种,分布于亚洲的中国、伊朗、日本、朝鲜等多个国家以及俄罗斯远东地区。该品种个体耐寒性强,适应利用南方冬季蜜源。']
seg_list = []
for sentence in sentences:
seg_list.append(", ".join(jieba.cut(sentence, cut_all=True)))
print("\n语料大小:{}\n{}".format(len(seg_list),seg_list))
keywords = jieba.analyse.extract_tags(sentences[0], topK=20, withWeight=True, allowPOS=('n','nr','ns'))
print("\n关键词大小:{}\n{}".format(len(keywords),keywords))
keywords = jieba.analyse.extract_tags(sentences[1], topK=20, withWeight=True, allowPOS=('n','nr','ns'))
print("\n关键词大小:{}\n{}".format(len(keywords),keywords))
1.2 Встраивание — практика Word2vec
Встраивание заключается в встраивании слов в пространство, состоящее из весов скрытых слоев нейронной сети, так что слова с похожей семантикой также близки по расстоянию в этом пространстве. Word2vec является выразительным методом в этой области.Общая структура сети выглядит следующим образом:
Входной слой — это слово, закодированное One-Hot, скрытый слой — это измерение внедрения, которое мы хотим получить, а выходной слой — это результат нашего предсказания на основе корпуса. Непрерывная итерация этой сети делает прогнозируемые результаты все ближе и ближе к реальным результатам, пока не произойдет сходимость, мы получим код встраивания слова, плотный вектор слов, содержащий семантическую информацию, который можно использовать в качестве входных данных для последующей модели.
Использованная литература:
Старый код некоторых версий данных недействителен. Обратитесь к учебной версии gensim, чтобы убедиться, что код можно запустить.
[1] : getting-started-with-word2vec-and-glove-in-python
[2]: обучение python︱gensim word2vec и связанным с ним функциям и функциональному пониманию.
[3]: использование word2vec в gensim
[4]: Использование word2vec в gensim.
1.1.1 Создание и обучение Word2vec с помощью собственного набора данных
import gensim
print("gensim 版本:",gensim.__version__)
# gensim 版本: 3.8.3
Gensim — это мощный инструмент обработки естественного языка, который включает в себя N многих распространенных моделей:
Базовые инструменты обработки корпуса, LSI, LDA, HDP, DTM, DIM, TF-IDF, word2vec, параграф2vec
Первый способ: самый простой метод тренировки (быстрый)
# 最简单的训练方式 - 一键训练
# 引入 word2vec
from gensim.models import word2vec
# 引入数据集
sentences = ['中华蜜蜂原产于中国,是中国的土著蜂,适应中国各地的气候和蜜源条件,适于定地饲养且稳产,尤其是在南方山区,有着其他蜂种不可替代的地位。',
'东方蜜蜂原产地在东方、简称东蜂,是蜜蜂属中型体中等的一个品种,分布于亚洲的中国、伊朗、日本、朝鲜等多个国家以及俄罗斯远东地区。该品种个体耐寒性强,适应利用南方冬季蜜源。']
seg_list = []
for sentence in sentences:
seg_list.append(" ".join(jieba.cut(sentence, cut_all=True)))
# 切分词汇
sentences = [s.split() for s in seg_list]
# 构建模型
model = word2vec.Word2Vec(sentences, min_count=1,size=100)
"""Word2Vec的参数
min_count:在不同大小的语料集中,我们对于基准词频的需求也是不一样的。譬如在较大的语料集中,我们希望忽略那些只出现过一两次的单词,
这里我们就可以通过设置min_count参数进行控制。一般而言,合理的参数值会设置在 0~100 之间。
size:参数主要是用来设置词向量的维度,Word2Vec 中的默认值是设置为 100 层。更大的层次设置意味着更多的输入数据,不过也能提升整体的准确度,合理的设置范围为 10~数百。
workers:参数用于设置并发训练时候的线程数,不过仅当Cython安装的情况下才会起作用。
"""
# 进行相关性比较
model.wv.similarity('东方','中国')
Второй метод: Поэтапный метод обучения (гибкий)
# 引入数据集
sentences = ['中华蜜蜂原产于中国,是中国的土著蜂,适应中国各地的气候和蜜源条件,适于定地饲养且稳产,尤其是在南方山区,有着其他蜂种不可替代的地位。',
'东方蜜蜂原产地在东方、简称东蜂,是蜜蜂属中型体中等的一个品种,分布于亚洲的中国、伊朗、日本、朝鲜等多个国家以及俄罗斯远东地区。该品种个体耐寒性强,适应利用南方冬季蜜源。']
seg_list = []
for sentence in sentences:
seg_list.append(" ".join(jieba.cut(sentence, cut_all=True)))
# 切分词汇
sentences = [s.split() for s in seg_list]
# 先启动一个空模型 an empty model
new_model = gensim.models.Word2Vec(min_count=1)
# 建立词汇表
new_model.build_vocab(sentences)
# 训练word2vec模型
new_model.train(sentences, total_examples=new_model.corpus_count, epochs=new_model.epochs)
# 进行相关性比较
new_model.wv.similarity('东方','中国')
Еще один эффект поэтапного обучения: поэтапное обучение.
# 增量训练
old_model = gensim.models.Word2Vec.load(temp_path)
# old_model = new_model
more_sentences = [['东北','黑蜂','分布','在','中国','黑龙江省','饶河县',','
,'它','是','在','闭锁','优越','的','自然环境','里',',','通过','自然选择','与','人工','进行','所','培育','的','中国','唯一','的','地方','优良','蜂种','。']]
old_model.build_vocab(more_sentences, update=True)
old_model.train(more_sentences, total_examples=model.corpus_count, epochs=model.epochs)
# 进行相关性比较
new_model.wv.similarity('东方','中国')
1.1.2 word2vec, импортированный из внешнего корпуса
Первый способ: загрузить корпус
# 外部语料引入 【text8】:http://mattmahoney.net/dc/text8.zip
sentences = word2vec.Text8Corpus('./text8')
model = word2vec.Word2Vec(sentences, size=200)
flag = False
if flag:
class Text8Corpus(object):
"""Iterate over sentences from the "text8" corpus, unzipped from http://mattmahoney.net/dc/text8.zip ."""
def __init__(self, fname, max_sentence_length=MAX_WORDS_IN_BATCH):
self.fname = fname
self.max_sentence_length = max_sentence_length
def __iter__(self):
# the entire corpus is one gigantic line -- there are no sentence marks at all
# so just split the sequence of tokens arbitrarily: 1 sentence = 1000 tokens
sentence, rest = [], b''
with utils.smart_open(self.fname) as fin:
while True:
text = rest + fin.read(8192) # avoid loading the entire file (=1 line) into RAM
if text == rest: # EOF
words = utils.to_unicode(text).split()
sentence.extend(words) # return the last chunk of words, too (may be shorter/longer)
if sentence:
yield sentence
break
last_token = text.rfind(b' ') # last token may have been split in two... keep for next iteration
words, rest = (utils.to_unicode(text[:last_token]).split(),
text[last_token:].strip()) if last_token >= 0 else ([], text)
sentence.extend(words)
while len(sentence) >= self.max_sentence_length:
yield sentence[:self.max_sentence_length]
sentence = sentence[self.max_sentence_length:]
Второй способ: метод загрузки файла модели
# 此种方法需保证有vectors.npy
model_normal = gensim.models.KeyedVectors.load('text.model')
model_binary = gensim.models.KeyedVectors.load_word2vec_format('text.model.bin', binary=True)
1.1.3 Методы хранения и чтения двух форматов word2vec
# 普通保存
model.wv.save('text.model')
# model = Word2Vec.load('text8.model')
model_normal = gensim.models.KeyedVectors.load('text.model')
# 二进制保存
model.wv.save_word2vec_format('text.model.bin', binary=True)
# model = word2vec.Word2Vec.load_word2vec_format('text.model.bin', binary=True)
model_binary = gensim.models.KeyedVectors.load_word2vec_format('text.model.bin', binary=True)
1.1.4 Как пользоваться обученным word2vec? Воспитание солдат на тысячу дней
# 相似度 比较
model.similarity('肖战', '王一博'),model.similarity('肖战', '张艺兴'),model.similarity('王一博', '张艺兴')
# 相近词 排列
model.most_similar(positive=['腾讯'], topn=10)
# 不相关词 识别
model.doesnt_match("早饭 中饭 晚饭 土豆 夜宵 加餐".split())
# 比较两个列表的相似度
model.n_similarity(['皇帝','国王',"朕","天子"],['陛下'])
# 得到词向量
model["重庆"]
# 获取词汇表
model.vocab.keys()
vocab = model.index2word[:100]
1.1.5 word2vec и среда глубокого обучения
Как word2vec сочетается с нейронными сетями?
- тензорная версия
- версия факела
Использованная литература:zhuanlan.zhihu.com/p/210808209
import numpy as np
import tensorflow as tf
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.utils import to_categorical
#导入word2vec模型并进行预处理
def w2v_model_preprocessing(content,w2v_model,embedding_dim,max_len=32):
# 初始化 `[word : index]` 字典
word2idx = {"_PAD": 0}
# 训练数据 词汇表构建
tokenizer = Tokenizer()
tokenizer.fit_on_texts(sentences)
vocab_size = len(tokenizer.word_index) # 词库大小
print(tokenizer.word_index)
error_count = 0
# 存储所有 word2vec 中所有向量的数组,其中多一位,词向量全为 0, 用于 padding
embedding_matrix = np.zeros((vocab_size + 1, w2v_model.vector_size))
print(embedding_matrix.shape)
for word, i in tokenizer.word_index.items():
if word in w2v_model:
embedding_matrix[i] = w2v_model.wv[word]
else:
error_count += 1
# 训练数据 词向量截断补全(padding)
seq = tokenizer.texts_to_sequences(sentences)
trainseq = pad_sequences(seq, maxlen=max_len,padding='post')
return embedding_matrix,trainseq
# 从文本 到 tf可用的word2vec
sentences = ['中华蜜蜂原产于中国,是中国的土著蜂,适应中国各地的气候和蜜源条件,适于定地饲养且稳产,尤其是在南方山区,有着其他蜂种不可替代的地位。',
'东方蜜蜂原产地在东方、简称东蜂,是蜜蜂属中型体中等的一个品种,分布于亚洲的中国、伊朗、日本、朝鲜等多个国家以及俄罗斯远东地区。该品种个体耐寒性强,适应利用南方冬季蜜源。']
seg_list = []
for sentence in sentences:
seg_list.append(" ".join(jieba.cut(sentence, cut_all=True)))
sentences = [s.split() for s in seg_list]
# 一些超参数
max_len = 64
embedding_dim = model.vector_size
embedding_matrix,train_data = w2v_model_preprocessing(sentences,model,embedding_dim,max_len)
embedding_matrix.shape,train_data.shape
from tensorflow.keras.models import Sequential,Model
from tensorflow.keras.models import load_model
from tensorflow.keras.layers import Dense,Dropout,Activation,Input, Lambda, Reshape,concatenate
from tensorflow.keras.layers import Embedding,Conv1D,MaxPooling1D,GlobalMaxPooling1D,Flatten,BatchNormalization
from tensorflow.keras.losses import categorical_crossentropy
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.regularizers import l2
def build_textcnn(max_len,embeddings_dim,embeddings_matrix):
#构建textCNN模型
main_input = Input(shape=(max_len,), dtype='float64')
# 词嵌入(使用预训练的词向量)
embedder = Embedding(
len(embeddings_matrix), #表示文本数据中词汇的取值可能数,从语料库之中保留多少个单词
embeddings_dim, # 嵌入单词的向量空间的大小
input_length=max_len, #规定长度
weights=[embeddings_matrix],# 输入序列的长度,也就是一次输入带有的词汇个数
trainable=False # 设置词向量不作为参数进行更新
)
embed = embedder(main_input)
flat = Flatten()(embed)
dense01 = Dense(5096, activation='relu')(flat)
dense02 = Dense(1024, activation='relu')(dense01)
main_output = Dense(2, activation='softmax')(dense02)
model = Model(inputs=main_input, outputs=main_output)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()
return model
TextCNN = build_textcnn(64,embedding_dim,embedding_matrix)
# 数据集加载
X_train, y_train = train_data,to_categorical([0,1], num_classes=2)
# 粗糙的模型训练
history = TextCNN.fit(X_train, y_train,
batch_size=2,
epochs=3,
verbose=1)
1.1.6 Метод визуализации word2vec
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
def wv_visualizer(model,word):
# 寻找出最相似的十个词
words = [wp[0] for wp in model.wv.most_similar(word,topn=10)]
# 提取出词对应的词向量
wordsInVector = [model.wv[word] for word in words]
wordsInVector
# 进行 PCA 降维
pca = PCA(n_components=2)
pca.fit(wordsInVector)
X = pca.transform(wordsInVector)
# 绘制图形
xs = X[:, 0]
ys = X[:, 1]
# draw
plt.figure(figsize=(12,8))
plt.scatter(xs, ys, marker = 'o')
for i, w in enumerate(words):
plt.annotate(
w,
xy = (xs[i], ys[i]), xytext = (6, 6),
textcoords = 'offset points', ha = 'left', va = 'top',
**dict(fontsize=10)
)
plt.show()
# 调用时传入目标词组即可
wv_visualizer(model,["man","king"])
НЛП новое, талант и обучение поверхностны, есть ошибки или несовершенства, прошу критиковать и исправлять! !