《FastText 工具使用》(四)训练文本分类

文本分类是一种自然语言处理(NLP)任务,旨在将文本数据分配到预定义的类别或标签中。在文本分类任务中,算法接收输入的文本数据,并根据其内容或语义特征将其分配到一个或多个类别中。

文本分类在许多现实世界的应用中都有广泛的应用,包括但不限于以下几个方面:

  1. 情感分析:将文本数据分类为积极、消极或中性等情感类别,用于分析用户评论、社交媒体帖子等的情感倾向。
  2. 垃圾邮件过滤:将电子邮件分类为垃圾邮件或非垃圾邮件,以过滤出用户不需要的信息。
  3. 新闻分类:将新闻文章分类到不同的主题类别,如政治、体育、科技等,以便用户更好地浏览和检索新闻内容。

https://fasttext.cc/docs/en/supervised-tutorial.html

1. 处理训练预料

在使用 FastText 训练文本分类模型时,输入数据需要满足以下要求:

  1. 数据格式:输入数据应该是一行一篇文档的格式
  2. 标签格式:每篇文档需要有一个或多个标签,标签应该用 __label__ 前缀表示,紧接着是标签的名称,多个标签之间用空格分隔。例如:__label__sports __label__football
  3. 数据处理:在输入数据之前,需要进行一些文本预处理,例如:分词、去除停用词、小写转换等
  4. 编码格式:确保文本数据的编码格式是 UTF-8 ,以避免出现编码问题导致的错误
  5. 数据量:FastText 对于大规模数据集的处理效果较好,建议使用大规模数据集进行训练
  6. 数据均衡:确保各个类别的样本数量相对均衡,以避免模型训练过程中的偏差
__label__标签1 __label__标签2 跟队 记者 活塞 裁掉 特雷肖 瑟曼 签下 特拉 德翁 霍林斯

通过满足上述要求,可以有效地利用 FastText 进行文本分类任务的训练。我们学习使用的数据集包含 14 个新闻类别,分为训练集(9000)、验证集(1400)、测试集(1400),具体每个标签数据分布如下:

# 测试集
{'房产': 100, '星座': 100, '教育': 100, '社会': 100, '家居': 100, '科技': 100, '时尚': 100, '娱乐': 100, '体育': 100, '时政': 100, '游戏': 100, '财经': 100, '彩票': 100, '股票': 100}

# 训练集
{'科技': 1813, '股票': 1733, '体育': 1408, '娱乐': 977, '时政': 696, '社会': 525, '教育': 458, '财经': 396, '家居': 343, '游戏': 219, '房产': 209, '时尚': 139, '彩票': 65, '星座': 19}

# 验证集
{'体育': 100, '科技': 100, '社会': 100, '娱乐': 100, '股票': 100, '房产': 100, '教育': 100, '时政': 100, '财经': 100, '星座': 100, '游戏': 100, '家居': 100, '彩票': 100, '时尚': 100}
# 读取停用词
stopwords = {word.strip() for word in open('data/stopwords.txt', encoding='utf-8')}

def clean_text(text):

    # 去除非中文字符
    text = re.sub(r'[^\u4e00-\u9fa5]', ' ', text)
    # 文本分词
    text =  jieba.cut(text)
    # 去除停用词
    clean_text = []
    for word in text:
        word = word.strip()
        if len(word) <= 1:
            continue
        if word not in stopwords:
            clean_text.append(word)

    return clean_text

# 数据处理
def preprocess():

    for fname in glob.glob('data/news/*.txt'):
        data = pd.read_csv(fname, sep='\t')
        news_list = []
        for news, target in data.to_numpy().tolist():
            news = clean_text(news)
            if len(news) == 0:
                continue
            news = ' '.join(news)
            news_list.append('__label__' + str(target) + ' ' + news + '\n')

        # 存储数据
        fname = os.path.basename(fname)
        open('temp/' + fname, 'w', encoding='utf-8').writelines(news_list)

2. 训练分类模型

2.1 简单使用

# 训练推理
def model_train():
    # 模型训练
    model = fasttext.train_supervised(input='temp/train.txt')
    # 模型评估 (测试集数量, P@1, R@1)
    print(model.test('temp/test.txt', threshold=0.0))
    # 模型推理
    print(model.predict(' '.join(clean_text('新浪体育讯 北京时间4月16日消息,火箭今天迎来常规赛的收官战。'))))
    # 模型存储
    model.save_model('temp/train.bin')

2.2 评估指标

P@K 和 R@K 是什么意思呢?

P@1 表示在模型只预测 1 个标签的情况下,预测正确的样本数量占预测标签数量的比重。
R@1 表示在模型只预测 1 个标签的情况下,预测正确的样本数量占总样本数量的比重。

P@2 表示在模型只预测 2 个标签的情况下,预测正确的样本数量占预测标签数量的比重。
R@2 表示在模型只预测 2 个标签的情况下,预测正确的样本数量占总样本数量的比重。

P@K 表示在模型只预测 K 个标签的情况下,预测正确的样本数量占预测标签数量的比重。
R@K 表示在模型只预测 K 个标签的情况下,预测正确的样本数量占总样本数量的比重。

例如,我们有 10 个样本,模型对每个样本预测 2 个标签:

  1. A(正确) B(错误)
  2. C(错误) B(正确)
  3. A(正确) D(错误)
  4. D(错误) B(错误)
  5. D(错误) A(错误)
  6. A(错误) C(正确)
  7. C(错误) D(错误)
  8. A(错误) C(错误)
  9. D(正确) B(错误)
  10. B(错误) D(错误)

总样本数量 10,总预测标签数量 20,预测正确的标签数量 5,则 P@2 = 5/20,R@2 = 5/10

# 评估指标
def model_train_method():
    model = fasttext.load_model('temp/train.bin')
    result = model.test('temp/test.txt', k=3, threshold=0.0)
    print(result)

    labels, inputs = [], []
    for line in open('temp/test.txt', encoding='utf-8'):
        line = line.split()
        labels.append(line[0])
        inputs.append(' '.join(line[1:]))


    preds = model.predict(inputs, k=3)[0]
    print(len(preds))

    right = 0
    for label, pred in zip(labels, preds):
        if label in pred:
            right += 1

    print(right/(result[0] * 3), right/result[0])

2.3 训练参数

  1. input:输入文件路径,包含用于训练的文本数据
  2. lr:学习率 (learning rate),控制模型参数更新的步长。默认值为 0.1
  3. dim:词向量的维度 (dimensionality),即每个词语被表示为多少维的向量。默认值为 100
  4. epoch:训练轮数 (number of epochs),即模型迭代训练的次数。默认值为 5
  5. minCount:词频阈值,低于该词频的词语将被忽略。默认值为 1
  6. wordNgrams:词袋模型中考虑的最大 n-gram 的长度。默认值为 1
  7. thread:线程数,用于并行处理。默认值为 12
  8. pretrainedVectors:预训练的词向量文件路径,可用于初始化词向量。默认值为空
# 训练参数
def model_train_param():
    # 模型训练
    model = fasttext.train_supervised(input='temp/train.txt',
                                      epoch=20,
                                      lr=9e-1,
                                      dim=300,
                                      loss='softmax',
                                      minCount=5,
                                      wordNgrams=1,
                                      pretrainedVectors='data/model/cc.zh.300.vec')
    # 模型评估 (测试集数量, P@1, R@1)
    print(model.test('temp/test.txt', threshold=0.0))

3. 自动参数搜索

Doc:https://fasttext.cc/docs/en/autotune.html

FastText 在训练模型时,可以通过以下参数来实现超参数的搜索:

  1. autotuneValidationFile:指定用于调优的验证集文件路径,评估模型在不同参数下的性能表现
  2. autotuneMetric:用于评估模型性能的指标,默认 f1 score
  3. autotuneDuration:模型调优的时间限制,当超过这个时间后,将停止搜索并返回最佳的参数
  4. autotuneModelSize:模型调优的模型大小限制

这些参数主要用于在 FastText 中进行模型调优的过程中,帮助用户自动地找到最佳的模型参数设置,以达到最佳的性能。Autotune 会根据验证数据和指定的性能指标,在一定的时间和模型大小限制下,尝试不同的参数组合,并返回性能最优的模型参数设置

# 自动调参
def model_autotune():
    # 训练模型,并自动调参
    model = fasttext.train_supervised(input='temp/train.txt',
                                      autotuneValidationFile='temp/valid.txt',
                                      autotuneDuration=30,
                                      autotuneMetric='f1',
                                      verbose=2)
    # 评估模型
    print('eval:', model.test('temp/test.txt', k=1, threshold=0.0))
    # 存储模型
    model.save_model('temp/autotune.bin')

4. 多标签分类

https://fasttext.cc/docs/en/supervised-tutorial.html#multi-label-classification

# 多标签分类
def model_train_multi_label():

    # 标签:组织关系裁员 财经交易出售收购
    # 数据:计算机行业大变革?甲骨文中国区裁员,IBM收购红帽公司
    text = '计算机行业 变革 甲骨文 中国区 裁员 收购 红帽 公司'

    model = fasttext.train_supervised(input='data/multi-label.txt', epoch=100, lr=5e-1, loss='ova')
    print(model.test('data/multi-label.txt'))
    print(model.predict(text, k=2, threshold=0.0))

下面是一个简单的例子,以帮助你理解多标签分类和 ova 方法:

假设有一个电影分类任务,我们想为电影分配以下标签:

  1. Romance(浪漫)
  2. Action(动作)
  3. Comedy(喜剧)

我们有以下几部电影及其标签:

  1. 《泰坦尼克号》 – Romance
  2. 《速度与激情》 – Action
  3. 《哈利·波特》 – Fantasy
  4. 《当哈利遇到萨莉》 – Romance, Comedy
  5. 《勇敢的心》 – Action, Drama
  6. 《超人》 – Action, Fantasy

使用 ova 方法,我们将每个标签视为一个独立的二分类任务。

  1. 对于 ‘Romance’ 标签:
    • 正类:《泰坦尼克号》, 《当哈利遇到萨莉》
    • 负类:《速度与激情》, 《哈利·波特》, 《勇敢的心》, 《超人》
  2. 对于 ‘Action’ 标签:
    • 正类:《速度与激情》, 《勇敢的心》, 《超人》
    • 负类:《泰坦尼克号》, 《哈利·波特》, 《当哈利遇到萨莉》
  3. 对于 ‘Comedy’ 标签:
    • 正类:《当哈利遇到萨莉》
    • 负类:《泰坦尼克号》, 《速度与激情》, 《哈利·波特》, 《勇敢的心》, 《超人》

我们使用上面的数据训练 3 个二分类模型。

5. 模型量化压缩

Doc:https://fasttext.cc/docs/en/python-module.html#compress-model-files-with-quantization

# 模型压缩
def model_quantization():
    # 加载模型
    model = fasttext.load_model('temp/autotune.bin')
    # 压缩模型
    model.quantize(input='temp/train.txt', retrain=True)
    # 评估模型
    print('eval:', model.test('temp/test.txt', k=1, threshold=0.0))

未经允许不得转载:一亩三分地 » 《FastText 工具使用》(四)训练文本分类
评论 (0)

1 + 3 =