NLP实战3--fasttext文本分类/数据准备

1.文本分类的目的

文本分类的目的就是意图识别,如果当前我们的项目下,只有两种意图需要被识别出来,对应的就是二分类问题,如果我们的聊天机器人有多个功能,那么我们需要分类的类别就有多个,就是一个多分类问题。例如,如果我们希望我们的聊天机器人能够播报当前的时间,那么我们就需要准备关于询问时间的语料,同时其目标值就是一个新的类别。在训练之后,通过这个新的模型,判断出用户询问的是当前的时间这个类别,那么就返回当前的时间。

同理,如果我们还希望聊天机器人能够播报未来一天的天气,那么这个机器人就还需要增添一个新的进行分类的意图,重新进行分类。

2.机器学习中常见的分类方法(朴素贝叶斯,随机森林等等)

2.1步骤

1.特征工程:对文本进行处理,转化为能够被计算的向量来表示,我们可以考虑使用所有的词语出现的次数,也可以考虑使用tf-idf来处理

2.对模型进行训练

3.对模型进行评估

2.2优化

使用机器学习的方法进行文本分类的时候,为了让结果更好,我们经常从两个角度出发

1.特征工程的过程中处理的更加细致,比如文本中的类似你我他,这种词语可以把它删除,某些词语出现的次数太少,可能并不具有代表意义,(tf-idf)某些词语出现太多,可能导致影响的程度过大等等都是可以考虑的地方

2.使用不同的算法进行训练,获取不同算法的结果,选择最好的或者是使用集成学习的方法(ensemble)

3.深度学习实现文本分类

常用操作:

1.对文本进行embedding的操作,转化为向量

2.之后再通过多层的神经网络进行线性和非线性的变化得到结果

3.变化后的结果和目标值进行计算得到损失函数,比如对数似然损失

4.通过最小化损失函数,去更新原来模型中的参数

4.fasttext的介绍

fasttext是一个单词表示学习和文本分类的库

优点:在标准的多核cpu上,能够训练10亿词级别语料库的词向量在十分钟之内,能够在一分钟之内给三十多万类别的50多万句子进行分类

fasttext模型输入一个词的序列(一段文本或一句话),输出这个词序列属于不同类别的概率

5.fasttext的基本使用

1.把数据准备为需要的格式

2.进行模型的训练、保存和加载、预测

#1.训练
model = fastText.train_supervised("./data/text_classify.txt", wordNgrams=1, epoch=20)
#2.保存
model.save_model("./data/ft_classify.model")
#3.加载
model = fastText.load_model("./data/ft_classify.model")

textlist = [句子1, 句子2]
#4.预测,传入句子列表
ret = model.predict(textlist)

6.数据准备

数据准备的最终需要的形式如下:

其中chat、QA字段可以自定义,就是目标值,__label__之前的为特征值,需要使用\t进行分隔,特征值需要进行分词,__label__后面的是目标值

6.1准备闲聊文本

这里使用的是小黄鸡的语料,地址:https://github.com/fateleak/dgk_lost_conv/tree/master/results

6.2把文本转化为需要的格式

对两部分文本进行分词,合并转化为需要的格式

完整过程

import pandas
from tqdm import tqdm
from lib.cut_sentence import cut
import config
import json
# 闲聊语料
xiaohuangji_path = "../../corpus/classify/origin_corpus/小黄鸡未分词.conv"
# 问答语料
byhand_path = "../../corpus/classify/origin_corpus/手动构造的问题.json"
crawled_path = "../../corpus/classify/origin_corpus/爬虫抓取的问题.csv"


def keywords_in_line(line):
    # 判断line中是否有不合要求的词
    keywords_list = ["传智播客", "传智", "黑马程序员", "黑马", "python"
                     , "人工智能", "c语言", "c++", "java", "javaee", "前端",
                     "移动开发", "ui", "ue", "大数据", "软件测试", "php", "h5", "产品经理",
                     "linux", "运维", "go语言", "区块链", "影视制作", "pmp", "项目管理", "新媒体",
                     "小程序"]
    for word in line:
        if word in keywords_list:
            return True
        else:
            return False

def process_xiaohuangji(file):
    """ 处理小黄鸡语料"""
    flag = 0
    num = 0
    for line in tqdm(open(xiaohuangji_path).readlines(), desc="xiaohuangji"):
        #TODO 句子长度为1 考虑删除
        if line.startswith("E"):  # 如果开头E 保留
            flag = 0
            continue
        elif line.startswith("M"): # 如果开头M 去掉M
            if flag==0:   # 第一个M出现
                line = line[1:].strip()
                flag = 1
            else: # 要不要第二个M
                continue  # continue表示不需要第二个出现的M开头的句子
        line_cuted =cut(line) # cut之后返回一个列表 然后用空格join到一起 转化成需要的格式
        if not keywords_in_line(line_cuted):
            line_cuted =" ".join(line_cuted) + "\t" + "__label__chat"
            num += 1
            file.write(line_cuted+"\n")
    return num

        # print(line_cuted)
        # 这里的路径很麻烦


def process():
    f = open(config.classify_corpus_path, "a")  # 要用a的方式读 append
    # 1.处理小黄鸡
    num_chat = process_xiaohuangji(f)
    # 2.处理手动构造的句子
    num_qa = process_byhand_data(f)
    # 3.处理抓取的句子
    num_qa1 = process_crawled_data(f)
    f.close()
    print(num_chat, num_qa, num_qa1)


def process_crawled_data(file):
    """处理抓取的数据"""
    num = 0
    for line in tqdm(open(crawled_path).readlines(),desc="crawled data"):
        line_cuted = cut(line)  # cut之后返回一个列表 然后用空格join到一起 转化成需要的格式
        line_cuted = " ".join(line_cuted) + "\t" + "__label__chat"
        num += 1
        file.write(line_cuted + "\n")


def process_byhand_data(file):
    """ 处理手动构造的数据"""
    total_lines = json.loads(open(byhand_path).read())
    num = 0
    for key in total_lines:
        for lines in tqdm(total_lines[key], desc="byhand"):
            for line in lines:
                if "校区" in line:
                    continue
                line_cuted = cut(line)  # cut之后返回一个列表 然后用空格join到一起 转化成需要的格式
                line_cuted = " ".join(line_cuted) + "\t" + "__label__chat"
                num += 1
                file.write(line_cuted + "\n")  # 这里的处理和之前相同
    return num



if __name__ == '__main__':
    process()

    # 执行之后就生成了我们需要的classify.txt

数据方法很重要! 下一步就是模型构造加训练 相比于模型构造 数据处理部分其实更为重要一些

你可能感兴趣的:(NLP实战记录,自然语言处理,分类,人工智能)