科赛网文本情感分类练习赛(一)

目的

通过实践学习新知识,逼迫自己尽快入门文本情感分类。同时要求自己做到坚持每日至少提交一次,并在博客中形成对应的文字记录,通过文字描述的形式,梳理自己的所思所得。

比赛简介

网址:https://www.kesci.com/home/competition/5c77ab9c1ce0af002b55af86
任务要求:对乌尔都语短文本进行情感二分类(最开始的时候我直接看成了英文……)

数据

训练文件 6328条,数据各字段描述如下图所示
训练文件的介绍

测试文件 2712条,无label标签,要求输出结果为正面情感极性的概率值,如下图所示
测试文件的介绍

数据预处理

提供的文件是csv文件,通过读取该文件,我发现这个文件并不是标准的csv文件,即字段内部存在换行符时,有的句子没有用双引号括起来。

train.csv 文件为例,就存在如下数据有问题:

['1413', 'Product theek hay.']
['but not worth that much price.', 'Negative']

['2027', '3 haftay tak koi baal nahi aaya skin per']
[' always buy from this vendor', 'Positive']

['5240', 'is product ko buy zaroooooor ki jiye']
[' Buhat acha hai ruzult is ka.', 'Positive']

读取数据的代码

import csv

import csv

def read_train_data(file_path):
    # 根据提供的路径,读取训练文件的数据,在训练文件中,ID是不需要的,所以不用管
    train_review_list = []
    train_label_list = []
    with open(file_path, 'r') as f:
        reader = csv.reader(f)
        next(reader, None)  # 跳过header
        for row in reader:
            if len(row)==3:
                train_review_list.append(row[1].strip())
                if row[2] == 'Positive':
                    train_label_list.append(1)
                else:
                    train_label_list.append(0)
            else:
                print(row)  # 打印有错的行记录
    return train_review_list, train_label_list


def read_test_data(file_path):
    # 根据提供的路径,读取测试文件的数据
    id_list = []
    review_list = []
    with open(file_path, 'r') as f:
        reader = csv.reader(f)
        next(reader, None)  # 跳过header
        for row in reader:
            if len(row)==2:
                id_list.append(row[0])
                review_list.append(row[1].strip())
            else:
                print(row)  # 打印有错的行记录
    return test_id_list, test_review_list

处理后的数据,点击下载,欢迎取用
train.csv下载
test.csv下载

解题思路

本次就是单纯的为了跑通整个流程,所以仅仅搭建一个非常简单的模型即可。
采用bert-as-service获取整个句子的BERT向量表示[参考文献1,2],然后采用sklearn中封装好的逻辑回归进行训练和预测。

结果

train.csv中分70%的数据作为训练集,30%的数据作为测试集,预测的准确率是 0.67
使用train.csv中所有数据作为训练集进行训练,对test.csv文件进行预测提交后的测评结果为 0.74
第一次提交结果

完整代码

import csv

def read_train_data(file_path):
    # 根据提供的路径,读取训练文件的数据,在训练文件中,ID是不需要的,所以不用管
    train_review_list = []
    train_label_list = []
    with open(file_path, 'r') as f:
        reader = csv.reader(f)
        next(reader, None)  # 跳过header
        for row in reader:
            if len(row)==3:
                train_review_list.append(row[1].strip())
                if row[2] == 'Positive':
                    train_label_list.append(1)
                else:
                    train_label_list.append(0)
            else:
                print(row)  # 打印有错的行记录
    return train_review_list, train_label_list


def read_test_data(file_path):
    # 根据提供的路径,读取测试文件的数据
    test_id_list = []
    test_review_list = []
    with open(file_path, 'r') as f:
        reader = csv.reader(f)
        next(reader, None)  # 跳过header
        for row in reader:
            if len(row)==2:
                test_id_list.append(row[0])
                test_review_list.append(row[1].strip())
            else:
                print(row)  # 打印有错的行记录
    return test_id_list, test_review_list


def save_result(file_path, test_id_list, pred_data):
    with open(file_path, mode="w") as outer:
        writer = csv.writer(outer)
        writer.writerow(["ID", "Pred"])
        for i in range(len(test_id_list)):
            writer.writerow([test_id_list[i], pred_data[i]])


if __name__ == '__main__':
    # 读取数据
    train_review_list, train_label_list = read_train_data(file_path='train.csv')
    test_id_list, test_review_list = read_test_data(file_path='test.csv')
    
    # 获取句子的bert词向量表示
    from bert_serving.client import BertClient
    bc = BertClient()  # 初始化客户端,连接服务器端,服务器端如何启动请参考文献1
    train_x_vectors = bc.encode(train_review_list)
    test_x_vectors = bc.encode(test_review_list)

    # 为方便自己在本地对模型的预测能力有一个基本的了解,所以需要在训练集中拆分出一部分作为验证集(或测试集)
    from sklearn.model_selection import train_test_split
    x_train, x_test, y_train, y_test = train_test_split(train_x_vectors, train_label_list, test_size=0.3,random_state=0)

    # 构建逻辑回归模型
    from sklearn.linear_model import LogisticRegression
    classifier = LogisticRegression()
    classifier.fit(x_train, y_train)
    # 在自己构造的测试集上进行测试
    from sklearn import metrics
    predictions = classifier.predict(x_test)  # 输出结果为0和1
    test_auc = metrics.roc_auc_score(y_test, predictions)  # 自己构造的测试集上的auc值
    print("在自己构造的测试集上的精度为:{}".format(test_auc))

    # 不拆分训练集,全部进行训练,预测test.csv
    classifier.fit(train_x_vectors, train_label_list)
    proba = classifier.predict_proba(test_x_vectors)
    positive_pred = proba[:, 1]  # 取正面情感极性的概率值

    # 保存结果
    save_result(file_path='out_test.csv', test_id_list=test_id_list, pred_data=positive_pred)

Reference

[1] hanxiao/bert-as-service
[2] google-research/bert
[3] BERT 中文预训练模型使用札记

TODO

  • 将句子的向量持久化,不用每次再重新计算

文章最后更新时间为:2019 年 03 月 05 日 15:34:45

添加新评论