fastText的核心思想就是:将整篇文档的词及n-gram向量叠加平均得到文档向量,然后使用文档向量做softmax多分类。
from keras.datasets import imdb
max_features = 20000 # 词典最大长度
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
ngram_range = 2 # 抽取的是二元组,可以自己定
max_features = 20000 # 词典最大长度
max_len = 400 # 刚刚通过 np.mean(list(map(len,x_train))) 查看了句子的平均长度 设置为400合适
batch_size = 32
embedding_dims = 100 # 每个单词的编码长度
epoch = 5 # 训练几个 epoch
def create_ngram_set(input_list, ngram_value=2):
'''
返回 不重复的 n_gram 词组
:param input_list: 输入的列表,也就是 imdb 数据中的每个样本(list形式)
:param ngram_value: 几元组
:return: 返回不重复的 n_gram 词组,用于做元组表
'''
return set(zip(*[input_list[i:] for i in range(ngram_value)]))
# 判断是否大于 1,大于1 就要加入多元词组特征
if ngram_range > 1:
ngram_set = set()
for input_list in x_train:
for i in range(2, ngram_range + 1):
# 抽取几元组
set_of_ngram = create_ngram_set(input_list, ngram_value=i)
ngram_set.update(set_of_ngram)
start_index = max_features + 1
# 将新生成的 n_gram 特征加入字典中
token_index_dict = {v: k + start_index for k, v in enumerate(ngram_set)}
index_token_dict = {token_index_dict[k]: k for k in token_index_dict}
max_features = len(list(token_index_dict.keys())) + 1
# 这个函数会在后面,就是将n_gram的信息 加入到原有的 字特征里
x_train = add_ngram(x_train, token_index_dict, ngram_range)
x_test = add_ngram(x_test, token_index_dict, ngram_range)
# 将数据的长度进行 padding 大于 maxlen 的截断, 小于 maxlen 的进行补全
x_train = sequence.pad_sequences(x_train, maxlen=max_len)
x_test = sequence.pad_sequences(x_test, maxlen=max_len)
def add_ngram(sequences, token_indice, ngram_range=2):
'''
对每一个句子进行 n_gram 特征的加入 生成 所有 token 的字典 和 index 字典
然后 遍历 sequences ,每一个句子 按照几元组的 形式分割,到 token_indice 中去索引,如果有值就加入
:param sequences: 【【word1,word2,word3.。。】,【word1,word2,word3.。。】。。。】
:param token_indice: 生成多元组和原始 token 的字典
:param ngram_range: n_gram 中的 n
:return: 返回新的 加入 n_gram 特征的列表中的列表
'''
new_sequences = []
for input_list in sequences:
# 将 列表 进行复制
new_list = input_list[:]
# 抽取几元组特征
for ngram_value in range(2, ngram_range + 1):
# 抽取 2 元组就在 len(list) 到 len(list)- 2 上进行选取
for i in range(len(new_list) - ngram_value + 1):
n_gram = tuple(input_list[i:i + ngram_value])
if n_gram in token_indice:
new_list.append(token_indice[n_gram])
new_sequences.append(new_list)
return new_sequences
class MyModel(keras.models.Model):
def __init__(self, max_features, embedding_dims, maxlen, num_class):
super(MyModel, self).__init__()
self.embedding1 = Embedding(max_features, embedding_dims,input_length=maxlen)
self.global_average_pool = GlobalAveragePooling1D()
self.dropout = Dropout(rate=0.2)
self.dense1 = Dense(num_class,activation='sigmoid')
self.dense2 = Dense(200,activation='relu')
def call(self, input):
x = self.embedding1(input)
x = self.global_average_pool(x)
x = self.dense2(x)
x = self.dropout(x)
x = self.dense1(x)
return x
num_class = 1
my_model = MyModel(max_features,embedding_dims,max_len,num_class)
my_model.compile(
loss='binary_crossentropy',
metrics=['accuracy'],
optimizer="adam"
)
my_model.fit(
x_train,
y_train,
batch_size=batch_size,
epochs=epoch,
validation_data=(x_test, y_test)
# , callbacks=call_back_list 这一块可以设置自己的回调函数 去做自己想做的事
)