本文系作者乐雨泉 (yuquanle) 投稿,作者公众号:AI小白入门(id: StudyForAI),欢迎关注,点击文末"阅读原文"可直达原文链接,也欢迎大家投稿,AI、NLP相关即可。
前段时间和朋友何从庆(AI算法之心)等队友一起组队参加了这个比赛,本来以为小比赛人少,没想到参加的人会有几千人。最后我们队伍取得季军(4st/3131),虽有些许遗憾,但是也很荣幸认识了更多的大佬。在此和队友整理总结了一波,放出答辩PPT以及开源了部分代码,希望对刚接触这个领域的小白新手能有些帮助~~~
竞赛背景
2018年人工智能的发展在运算智能和感知智能已经取得了很大的突破和优于人类的表现。而在以理解人类语言为入口的认知智能上,目前达观数据自然语言处理技术已经可以实现文档自动解析、关键信息提取、文本分类审核、文本智能纠错等一定基础性的文字处理工作,并在各行各业得到充分应用。
自然语言处理一直是人工智能领域的重要话题,而人类语言的复杂性也给 NLP 布下了重重困难等待解决。长文本的智能解析就是颇具挑战性的任务,如何从纷繁多变、信息量庞杂的冗长文本中获取关键信息,一直是文本领域难题。随着深度学习的热潮来临,有许多新方法来到了 NLP 领域,给相关任务带来了更多优秀成果,也给大家带来了更多应用和想象的空间。
此次比赛,达观数据提供了一批长文本数据和分类信息,希望选手动用自己的智慧,结合当下最先进的NLP和人工智能技术,深入分析文本内在结构和语义信息,构建文本分类模型,实现精准分类。未来文本自动化处理的技术突破和应用落地需要人工智能从业者和爱好者的共同努力,相信文本智能处理技术因为你的算法,变得更加智能!
比赛网址
http://www.dcjingsai.com/common/cmpt/%E2%80%9C%E8%BE%BE%E8%A7%82%E6%9D%AF%E2%80%9D%E6%96%87%E6%9C%AC%E6%99%BA%E8%83%BD%E5%A4%84%E7%90%86%E6%8C%91%E6%88%98%E8%B5%9B_%E7%AB%9E%E8%B5%9B%E4%BF%A1%E6%81%AF.html
答辩PPT
详细解决方案
对于这个比赛,我们尝试了很多方法,最后我们发现了一些对解决这个赛题很不错的解决方案(当然,对于其他任务也可以起到不错的效果)。总结如下:
通过对于词向量做一个增强,即利用word2vec与glove的差异性,构建一个鲁棒性更高的词语向量表征。具体而言,我们对于每个词通过word2vec以及glove分别训练出两个200维度的词量,两种向量相结合,表征出更强的语义信息,从而得到一个 400维度的词向量。大家也可以word2vec+glove+faxttext的组合,对于我来说,效果并不是很好,我觉得可能的原因是faxttext与word2vec的相似性很高,弱化了glove的向量表征,同时,对于glove单独的词向量我也没有尝试过,大家也可以尝试一下。
对于模型的话,选择了一个比较简单的模型,两个双向的GRU模型,然后分别平均池化和最大池化,最后接到FC层。
训练的方式:训练模型我们固定了100个epoch,然后使用早停的策略,根据验证集上的性能,选择验证数据集上具有最佳准确率分数的模型作为最终模型,并评估其在测试数据集上的性能。
代码如下
1. 导入各个算法库,导入数据集,数据集路径根据自己的路径设置。
train=pd.read_csv("../input/train_set.csv")
test=pd.read_csv("../input/test_set.csv")
2. 词向量维度选取以及句子长度截断一般方法。
对于句子长度选择:统计下每条句子的长度,一般可以看置信区间在90,95,98的句子长度,比如有三条句子,句子中分别有2000,1800,1900个词。因此,基于此代码np.percentile([2000,1800,1900],95),可以得到置信区间在95的句子长度为1990。
对于词向量的维度:可以尝试100,200,300等,对于不同的维度,测试模型的效果,从而选择一个相对较好的维度。
tokenizer = text.Tokenizer(num_words=args.num_words, lower=False,filters="")
tokenizer.fit_on_texts(list(df_train[col].values)+list(df_test[col].values))
train_ = sequence.pad_sequences(tokenizer.texts_to_sequences(df_train[col].values), maxlen=maxlen_)
test_ = sequence.pad_sequences(tokenizer.texts_to_sequences(df_test[col].values), maxlen=maxlen_)
word_index = tokenizer.word_index
#词向量训练代码可以在github上面查看,下面是生成词向量嵌入矩阵
embedding_word2vec_matrix = np.zeros((len(word_index) + 1, victor_size))
for word, i in word_index.items():
embedding_vector = model[word] if word in model else None
if embedding_vector is not None:
count += 1
embedding_word2vec_matrix[i] = embedding_vector
else:
unk_vec = np.random.random(victor_size) * 0.5
unk_vec = unk_vec - unk_vec.mean()
embedding_word2vec_matrix[i] = unk_vec
3. 模型构建
本次开源一个比较简单的模型,利用双层的BiGRU模型来学习文本的上下文表征,然后通过池化操作,分别提取每一个时间戳的最大池化和平均池化。最后通过FC层的训练,构建文本分类模型,实现精准分类。
def bi_gru_model(sent_length, embeddings_weight,class_num):
print("get_text_gru3")
content = Input(shape=(sent_length,), dtype='int32')
embedding = Embedding(
name="word_embedding",
input_dim=embeddings_weight.shape[0],
weights=[embeddings_weight],
output_dim=embeddings_weight.shape[1],
trainable=False)
x = SpatialDropout1D(0.2)(embedding(content))
x = Bidirectional(CuDNNGRU(200, return_sequences=True))(x)
x = Bidirectional(CuDNNGRU(200, return_sequences=True))(x)
avg_pool = GlobalAveragePooling1D()(x)
max_pool = GlobalMaxPooling1D()(x)
conc = concatenate([avg_pool, max_pool])
x = Dropout(0.2)(Activation(activation="relu")(BatchNormalization()(Dense(1000)(conc))))
x = Activation(activation="relu")(BatchNormalization()(Dense(500)(x)))
output = Dense(class_num, activation="softmax")(x)
model = Model(inputs=content, outputs=output)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
4. 模型训练
对于模型的训练,我们采用10折交叉进行训练,为了减少时间,可以进行5折交叉进行训练。训练模型我们固定了100个epoch,然后使用早停的策略,根据验证集上的性能,选择验证数据集上具有最佳准确率分数的模型作为最终模型,并评估其在测试数据集上的性能。
model = bi_gru_model(word_seq_len, word_embedding,19)
early_stopping = EarlyStopping(monitor='val_acc', patience=6)
plateau = ReduceLROnPlateau(monitor="val_acc", verbose=1, mode='max', factor=0.5, patience=3)
checkpoint = ModelCheckpoint('../cache/model.hdf5', monitor='val_acc', verbose=2, save_best_only=True, mode='max',save_weights_only=True)
model.fit(X_train, y_train,
epochs=100,
batch_size=args.batch_size,
validation_data=(X_valid, y_valid),
callbacks=[early_stopping, plateau, checkpoint],
verbose=2)
写在后面
本项目主要利用“达观杯”文本比赛的数据,介绍了长文本分类问题的解决方法。我们通过利用两层的BiGRU捕捉长文本的上下文信息,然后通过池化层捕捉最关键的文本特征,接着两层的全连接层对文本的关键特征进行训练,从而构建文本分类模型,实现精准分类。另外,我们通过10折交叉的方式,测试集线上的分数可以达到0.798,仅仅这个单模型可以达到线上前10的效果(在线上赛时)。另外,为了节省运行时间,可以将10折交叉变成5折交叉,减少运行时间。同时,也可以将BiGRU减少一层。
如果您需要答辩PPT,可以关注"AI小白入门",后台回复"DGJJ"(建议复制)获取。
完整可运行代码以及PPT可以在我的github找到:
https://github.com/yuquanle/2018-daguan-competition-rank4
完整可运行代码以及PPT可以在我的github找到:
https://github.com/yuquanle/2018-daguan-competition-rank4
长按二维码关注~
AI小白入门
ID: StudyForAI
学习AI学习ai(爱)
期待与您的相遇~