tensorflow + fasttext 实现文本分类及原理

1 fasttext原理简介

fasttext是2016年facebook的Joulin、Mikolov等人提出来的一种高效文本分类的算法,相比于其他神经网络模型而言,fasttext模型网络结构更加简单、运行起来更加快速,并且模型保持了较高的准确度。用论文原文的话说,训练10亿级别的数据量只需要10分钟。原文链接:https://arxiv.org/abs/1607.01759

2 数据介绍

本文使用的数据集为网站爬取的短文本评论,其中由于数据量较少,不区分验证集与测试集,并按照4:1的比例将原始有标签数据分为训练集与测试集。
原始数据文件压缩包网盘链接:https://pan.baidu.com/s/13vwd3lfKWfXlD1a8uB6ngg
提取码:urj2
注:解压后的text_data文件夹放置在与程序的同级目录下。
原始数据以txt文本格式保存,标签分为pos与neg,因此预处理主要是将标签与数据分开对应保存,并将数据分为训练集与测试集。

3 数据预处理

import os
# 获取text_data文件夹下的所有文件路径
temp_list = list(os.walk(r"text_data"))
original = temp_list[0][0]
file_name = temp_list[0][2]
path_list = [original + "\\" + eve_name for eve_name in file_name]
# 创建所需文件
train_data = open(r"train_data.txt", "w", encoding="utf-8")
train_label = open(r"train_label.txt", "w", encoding="utf-8")
test_data = open(r"test_data.txt", "w", encoding="utf-8")
test_label = open(r"test_label.txt", "w", encoding="utf-8")
vocabulary = open(r"vocabulary.txt", "w", encoding="utf-8")
# 将原始数据进行标签分离与训练测试集分离
for every_path in path_list:
    with open(every_path, "r", encoding="utf-8") as temp_file:
        corpus = [eve for eve in temp_file if len(eve.strip("\n")) != 0]
        limit1 = len(corpus)*0.9
        limit2 = len(corpus)*0.1
        for i in range(len(corpus)):
            if limit2 < i < limit1:
                if corpus[i][:3] == "pos":
                    train_data.write(corpus[i][3:])
                    train_label.write("1" + "\n")
                else:
                    train_data.write(corpus[i][3:])
                    train_label.write("0" + "\n")
            else:
                if corpus[i][:3] == "pos":
                    test_data.write(corpus[i][3:])
                    test_label.write("1" + "\n")
                else:
                    test_data.write(corpus[i][3:])
                    test_label.write("0" + "\n")
# 创建字库vocabulary_2gram,包含原始数据中所有的字,写入vocabulary.txt待用
from nltk.util import ngrams
with open(r"test_data.txt", "r", encoding="utf-8") as file1:
	corpus1 = [eve for eve in file1]
with open(r"train_data.txt", "r", encoding="utf-8") as file2:
	corpus2 = [eve for eve in file2]
with open(r"vocabulary_2gram.txt","w",encoding="utf-8") as file3:
	word_list = []
    corpus = corpus1 + corpus2
     for line in corpus:
         word_list.append([char for char in line])
     _2gramword_list = []
     for eve in word_list:
         temp = ngrams(eve,2)
         for turple in temp:
             _2gramword_list.append(turple[0]+turple[1])
     word_list = list(set(_2gramword_list))
     for word in word_list:
         file3.write(word + "\n")

4 fasttext实现文本分类

from nltk.util import ngrams
import tensorflow.contrib.keras as kr
import tensorflow as tf

with open(r"train_data.txt", "r", encoding="utf-8") as file1:
    corpus = [eve.strip("\n") for eve in file1]
with open(r"vocabulary_2gram.txt", "r", encoding="utf-8") as file2:
    vocabulary = [word.strip("\n") for word in file2]
with open(r"train_label.txt", "r", encoding="utf-8") as file3:
    label_list = [int(eve.strip("\n")) for eve in file3]
assert len(label_list) == len(corpus)

word2id = {word:id_ for id_, word in enumerate(vocabulary)}
def line2id_2gram(line):
    temp = []
    for char in line:
        temp.append(char)
    tep = [eve[0] + eve[1] for eve in ngrams(temp,2)]
    return [word2id[word] for word in tep]
train_list = [line2id_2gram(line) for line in corpus]
train_x = kr.preprocessing.sequence.pad_sequences(train_list, 100)  # 长度一致train_x
train_y = kr.utils.to_categorical(label_list, num_classes=2)
tf.compat.v1.reset_default_graph()
X_holder = tf.compat.v1.placeholder(tf.int32, [None, 100])  # 占位
Y_holder = tf.compat.v1.placeholder(tf.float32, [None, 2])

# 做词嵌入工作 注意71166是自由生成的行向量,这里是构建的vocabulary_2gram.txt中的大小
embedding = tf.compat.v1.get_variable('embedding', [71166, 60])  # 一种初始化变量的方法,随机初始化了矩阵变量
embedding_inputs = tf.nn.embedding_lookup(embedding, X_holder)  # lookup


# 神经网络结构 输入-取平均-softmax二分类器-输出
mean = tf.reduce_mean(embedding_inputs, axis=1)  # 将句子中的字按照字向量取平均值
logits = tf.layers.dense(mean, 2)  # 接一个60:2的softmax的分类器

learning_rate = tf.train.polynomial_decay(1e-2, 0, 1)  # rate = (rate - 0.0001) *(1 - 0 / 1) ^ (1) +0.0001

cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(labels=Y_holder, logits=logits)
loss = tf.reduce_mean(cross_entropy)  # 熵的平均值
optimizer = tf.train.AdamOptimizer(learning_rate)  # 定义优化器
train = optimizer.minimize(loss)  # 将优化器与损失值连接起来

isCorrect = tf.equal(tf.argmax(Y_holder, 1), tf.argmax(logits, 1))  # 判断是否正确
accuracy = tf.reduce_mean(tf.cast(isCorrect, tf.float32))  # 判断准确率

init = tf.global_variables_initializer()
session = tf.Session()
session.run(init)

with open(r"test_data.txt", "r", encoding="utf-8") as file4:
    corpus_ = [eve.strip("\n") for eve in file4]
with open(r"test_label.txt", "r", encoding="utf-8") as file5:
    label_list_ = [int(eve.strip("\n")) for eve in file5]
assert len(label_list_) == len(corpus_)
test_list = [line2id_2gram(line) for line in corpus_]
test_x = kr.preprocessing.sequence.pad_sequences(test_list, 100)  # 长度一致train_x
test_y = kr.utils.to_categorical(label_list_, num_classes=2)

import random
for i in range(3000):
    selected_index = random.sample(list(range(len(train_y))), k=60)  # 批训练大小的意思就是多少个样本调整一次参数
    batch_X = train_x[selected_index]
    batch_Y = train_y[selected_index]
    session.run(train, {X_holder:batch_X, Y_holder:batch_Y})
    step = i + 1
    if step % 100 == 0:
        selected_index = random.sample(list(range(len(test_y))), k=150)
        batch_X = test_x[selected_index]
        batch_Y = test_y[selected_index]
        loss_value, accuracy_value = session.run([loss, accuracy], {X_holder:batch_X, Y_holder:batch_Y})
        print('step:%d loss:%.4f accuracy:%.4f' %(step, loss_value, accuracy_value))

5 运行结果

step:100 loss:0.2895 accuracy:0.8800
step:200 loss:0.2355 accuracy:0.8933
step:300 loss:0.1878 accuracy:0.9333
step:400 loss:0.3736 accuracy:0.8933
step:500 loss:0.2616 accuracy:0.8867
step:600 loss:0.2473 accuracy:0.9133
step:700 loss:0.1472 accuracy:0.9333
step:800 loss:0.3756 accuracy:0.8933
step:900 loss:0.2291 accuracy:0.9333
step:1000 loss:0.2153 accuracy:0.9200
step:1100 loss:0.2682 accuracy:0.9000
step:1200 loss:0.2792 accuracy:0.9133
step:1300 loss:0.2163 accuracy:0.9267
step:1400 loss:0.3535 accuracy:0.8867
step:1500 loss:0.2507 accuracy:0.9133
step:1600 loss:0.2644 accuracy:0.9000
step:1700 loss:0.4856 accuracy:0.8600
step:1800 loss:0.3144 accuracy:0.8800
step:1900 loss:0.2887 accuracy:0.8733
step:2000 loss:0.3268 accuracy:0.9067
step:2100 loss:0.3687 accuracy:0.8667
step:2200 loss:0.2661 accuracy:0.9267
step:2300 loss:0.3162 accuracy:0.9133
step:2400 loss:0.5905 accuracy:0.8733
step:2500 loss:0.3979 accuracy:0.8800
step:2600 loss:0.3052 accuracy:0.9333
step:2700 loss:0.3631 accuracy:0.9600
step:2800 loss:0.3845 accuracy:0.9200
step:2900 loss:0.5608 accuracy:0.8800
step:3000 loss:0.1405 accuracy:0.9400

结果准确度还可以,并且模型的运行速度非常快。根据作者原文的说法,fasttext比较适合解决样本量大,并且类标签种类比较多的数据集。另外,本文实现的fasttext实际上只实现了模型结构与Ngram特征提取,层次softmax并未实现,因为解决的问题不是多分类的问题。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 以下是使用 fasttext 进行文本分类的示例代码: ``` import fasttext # 训练模型 classifier = fasttext.train_supervised(input="data.train", lr=1.0, epoch=25, wordNgrams=2) # 预测 texts = ["I love playing football", "I hate playing football"] labels, probs = classifier.predict(texts) print(labels) # 输出预测的标签 print(probs) # 输出预测的概率 # 评估模型 print(classifier.test("data.valid")) ``` 其中,"data.train" 是训练集文件路径,"data.valid" 是验证集文件路径,可根据自己的数据进行修改。 在这个例子中,我们使用了一个超参数wordNgrams=2,意味着我们把两个连续的单词组合成一个特征。 ### 回答2: FastText 是一个基于词袋模型的文本分类工具,采用了层次 Softmax 进行多层分类。以下是使用 FastText 实现文本分类的示例代码: 首先,需要安装 fasttext 库,并导入相应的模块: ``` !pip install fasttext import fasttext ``` 接下来,准备训练数据和测试数据。假设文本分类的目标是将电影评论分为积极和消极两类。训练数据和测试数据分别保存在 train.txt 和 test.txt 文件中,每行包含一个标签和一个句子,以空格分隔,例如: ``` __label__positive 这部电影真的很棒 __label__negative 这个电影太糟糕了 ``` 创建 FastText 的分类器,并设置一些模型参数: ``` classifier = fasttext.supervised('train.txt', 'model', label_prefix='__label__') ``` 使用训练数据训练模型: ``` classifier = fasttext.train_supervised('train.txt', label_prefix='__label__') ``` 对测试数据进行预测: ``` result = classifier.predict('test.txt') ``` 输出预测结果: ``` print(result) ``` 以上就是使用 FastText 实现文本分类的示例代码。通过训练和预测,可以对新的文本数据进行分类,并获得分类结果。需要注意的是,这只是一个简单的示例,实际应用中还需要进行更多的数据预处理、模型调参和评估等工作。 ### 回答3: 以下是使用fasttext实现文本分类的示例代码: ```python import pandas as pd import fasttext # 读取训练数据 train_data = pd.read_csv('train_data.csv') # 将训练数据写入文本文件 train_data['text_label'] = '__label__' + train_data['label'].astype(str) + ' ' + train_data['text'] train_data[['text_label']].to_csv('train.txt', index=False, header=False, sep='\t') # 训练模型 model = fasttext.train_supervised(input='train.txt', epoch=10, lr=1.0, wordNgrams=2) # 保存模型 model.save_model('model.bin') # 加载模型 model = fasttext.load_model('model.bin') # 预测文本分类 text = '这是一个测试文本' predicted_label = model.predict(text) print(predicted_label[0][0]) # 输出预测的类别 ``` 首先,要准备好训练数据,数据格式为CSV文件,包含两列:label和text,其中label代表文本类别,text代表文本内容。 读取训练数据后,将label和text合并,形成fasttext所需的标签格式。然后将标签格式的数据写入文本文件(train.txt)中,每行包含一个文本的标签和内容。 使用`fasttext.train_supervised`函数来训练文本分类模型,指定输入文件、迭代次数、学习率和wordNgrams等参数。 训练完成后,保存模型为二进制文件(model.bin)。 加载模型后,使用`model.predict`函数对文本进行分类预测,得到预测的类别。 最后打印出预测的类别。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值