前段时间和朋友何从庆(AI算法之心)等队友一起组队参加了这个比赛,本来以为小比赛人少,没想到参加的人会有几千人。最后我们队伍取得季军(4st/3131),虽有些许遗憾,但是也很荣幸认识了更多的大佬。在此和队友整理总结了一波,放出答辩PPT以及开源了部分代码,希望对刚接触这个领域的小白新手能有些帮助~~~
比赛网址
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
详细解决方案
对于这个比赛,我们尝试了很多方法,最后我们发现了一些对解决这个赛题很不错的解决方案(当然,对于其他任务也可以起到不错的效果)。总结如下:
代码如下
1. 导入各个算法库,导入数据集,数据集路径根据自己的路径设置。
train=pd.read_csv("../input/train_set.csv")
test=pd.read_csv("../input/test_set.csv")
2. 词向量维度选取以及句子长度截断一般方法。
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可以在作者的github找到:
https://github.com/yuquanle/2018-daguan-competition-rank4