当前位置:   article > 正文

12-NLP之Bert实现文本分类_bert文本分类

bert文本分类

1. 代码展示


x = [1, 2, 3]  # list
print(x[:10] + [0] * -7) #  [1, 2, 3]
print(x[:10] + [0] * 7)  # [1,2,3,0,0,0,0,0,0,0]
  • 1
  • 2
  • 3
  • 4
from tqdm import tqdm  # 可以在循环中添加进度条
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")

labels = []
train_list = []
with open("../data/ChnSentiCorp.txt", mode='r', encoding='utf-8') as file:
    for line in tqdm(file.readlines()):
        line = line.strip().split(',')
        labels.append(int(line[0]))
        text = tokenizer.encode(line[1])
        token = text[:80] + [0] * (80 - len(text))
        train_list.append(token)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
import numpy as np

labels = np.array(labels)
train_list = np.array(train_list)

# 已经把数据转化成了词向量 (Bert不需要词嵌入)  RNN --> LSTM
from transformers import TFBertForSequenceClassification

model = TFBertForSequenceClassification.from_pretrained("bert-base-chinese", num_labels=2)

model.compile(loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.summary()
result = model.fit(x=train_list, y=labels, batch_size=128, epochs=10)
print(result.history)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2. 整体流程介绍

首先,概述一下代码的主要目的和流程。

主要目的
此代码的主要目的是使用BERT模型进行序列分类。具体来说,它似乎是在处理某种情感分析任务,因为代码中读取了标签和文本,并试图用BERT模型来进行分类(假设为正面或负面情感,因为num_labels=2)。

整体流程

  1. 导入所需库

    • tqdm:用于显示循环的进度条。
    • transformers:提供预训练的模型和相关的工具。
  2. 数据预处理

    • 定义了两个空列表labelstrain_list,用于存储从文件中读取的标签和文本数据。
    • 打开一个名为ChnSentiCorp.txt的文件,并从中读取数据。假设每行的格式是“标签,文本”。
    • 使用BERT的tokenizer将每行文本转化为token。然后,确保每行文本的token长度为80,如果长度不足80,则用0填充。
  3. 转换数据格式

    • 将labels和train_list列表转换为numpy数组。
  4. 加载和初始化BERT模型

    • 使用TFBertForSequenceClassification.from_pretrained方法加载bert-base-chinese预训练模型,并指定类别数量为2。
    • 编译模型,设置损失函数和评估指标,并显示模型摘要。
  5. 模型训练

    • 使用处理后的train_list作为输入和labels作为目标进行模型训练。
    • 显示训练历史。

综上,代码的整体流程是:导入库→数据预处理→数据格式转换→加载和初始化BERT模型→模型训练。

3. 代码解读

像debug一样逐步解释代码。

from tqdm import tqdm  # 可以在循环中添加进度条
  • 1

这一行导入了tqdm库,它是一个在循环中显示进度条的库。


x = [1, 2, 3]  # list
print(x[:10] + [0] * -7)
  • 1
  • 2

这里首先定义了一个列表x。接下来,x[:10]表示获取列表x的前10个元素,但因为x只有3个元素,所以它其实会返回整个x。[0] * -7将产生一个空列表,因为乘以一个负数的结果是空。所以print语句的输出将是[1, 2, 3]


from transformers import AutoTokenizer
  • 1

这里从transformers库中导入了AutoTokenizertransformers库提供了很多预训练模型及其相关的工具,AutoTokenizer是其中的一个。


tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")
  • 1

使用bert-base-chinese这个预训练模型的tokenizer。这个tokenizer是针对中文BERT模型的。


labels = []
train_list = []
with open("../data/ChnSentiCorp.txt", mode='r', encoding='utf-8') as file:
    for line in tqdm(file.readlines()):
        line = line.strip().split(',')
        labels.append(int(line[0]))
        text = tokenizer.encode(line[1])
        token = text[:80] + [0] * (80 - len(text))
        train_list.append(token)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这段代码读取文件ChnSentiCorp.txt并从中获取标签和文本数据。每一行都是由一个标签和文本组成的,两者之间用逗号分隔。文本数据被tokenized并被截断或填充至长度80。


import numpy as np

labels = np.array(labels)
train_list = np.array(train_list)
  • 1
  • 2
  • 3
  • 4

这里首先导入了numpy库,并将labels和train_list转换为numpy数组。


from transformers import TFBertForSequenceClassification
  • 1

transformers库中导入了用于序列分类的TFBert模型。


model = TFBertForSequenceClassification.from_pretrained("bert-base-chinese", num_labels=2)
  • 1

初始化一个预训练的BERT模型用于序列分类。这里指定了类别数量为2。


model.compile(loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.summary()
  • 1
  • 2

模型被编译,使用了sparse_categorical_crossentropy作为损失函数,并设置了accuracy作为评估指标。model.summary()会显示模型的结构和参数信息。

model.summary()会输出如下内容。

Model: "tf_bert_for_sequence_classification"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 bert (TFBertMainLayer)      multiple                  102267648 
                                                                 
 dropout_37 (Dropout)        multiple                  0         
                                                                 
 classifier (Dense)          multiple                  1538      
                                                                 
=================================================================
Total params: 102,269,186
Trainable params: 102,269,186
Non-trainable params: 0
_________________________________________________________________
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

result = model.fit(x=train_list, y=labels, batch_size=128, epochs=10)
  • 1

在机器学习和深度学习中,batch_size 是一个重要的概念。它的含义以及它在训练过程中的作用:

  1. Batch Size 定义

    • batch_size 指的是在训练神经网络时,每次传递给网络并进行处理的样本数量。简而言之,它是每次迭代中网络看到的数据量。
  2. 工作原理

    • 在训练过程中,整个数据集被分割成多个小批量(batches)。每个批量包含了一定数量的样本,这个数量就是 batch_size
    • 网络在每个批量上进行权重更新。这意味着,每处理一个批量,网络的参数就会根据这个批量上的数据进行一次更新。
  3. 为什么重要

    • 内存效率:较小的 batch_size 可以减少内存的使用,因为每次只处理一小部分数据。
    • 训练稳定性:较大的 batch_size 通常能让训练过程更稳定,但可能需要更多的内存和计算资源。
    • 泛化能力:较小的 batch_size 有时可以提高模型的泛化能力,但也可能导致训练过程中的噪音增多。
  4. 选择合适的 Batch Size

    • 选择合适的 batch_size 取决于多种因素,包括可用的内存大小、训练数据的特性以及所使用的优化算法。通常,这需要通过实验来确定。

在上面的代码 result = model.fit(x=train_list, y=labels, batch_size=128, epochs=10) 中,batch_size=128 意味着每次迭代过程中,模型将处理 128 个训练样本。这是在权重更新前网络将看到的数据量。

Epoch 1/10
61/61 [==============================] - 2293s 36s/step - loss: 0.9221 - accuracy: 0.3204
Epoch 2/10
61/61 [==============================] - 2139s 35s/step - loss: 0.6931 - accuracy: 0.3147
Epoch 3/10
61/61 [==============================] - 2078s 34s/step - loss: 0.6931 - accuracy: 0.3147
Epoch 4/10
61/61 [==============================] - 1897s 31s/step - loss: 0.6931 - accuracy: 0.3147
Epoch 5/10
61/61 [==============================] - 1898s 31s/step - loss: 0.6931 - accuracy: 0.3147
Epoch 6/10
61/61 [==============================] - 1904s 31s/step - loss: 0.6931 - accuracy: 0.3147
Epoch 7/10
61/61 [==============================] - 1895s 31s/step - loss: 0.6931 - accuracy: 0.3147
Epoch 8/10
61/61 [==============================] - 1887s 31s/step - loss: 0.6931 - accuracy: 0.3147
Epoch 9/10
61/61 [==============================] - 1878s 31s/step - loss: 0.6931 - accuracy: 0.3147
Epoch 10/10
61/61 [==============================] - 1875s 31s/step - loss: 0.6931 - accuracy: 0.3147
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
print(result.history)
  • 1
{'loss': [0.9221097230911255, 0.6931471228599548, 0.6931471228599548, 0.6931471228599548, 0.6931471228599548, 0.6931471228599548, 0.6931471228599548, 0.6931471228599548, 0.6931471228599548, 0.6931471228599548], 
'accuracy': [0.3204120993614197, 0.3147456645965576, 0.3147456645965576, 0.3147456645965576, 0.3147456645965576, 0.3147456645965576, 0.3147456645965576, 0.3147456645965576, 0.3147456645965576, 0.3147456645965576]
}
  • 1
  • 2
  • 3

模型训练过程。使用train_list作为输入数据,labels作为标签。批大小设置为128,总共训练10轮。训练完毕后,会打印训练历史数据。

4. 报错解决

执行下面的代码的时候报错:

from transformers import TFBertForSequenceClassification
model = TFBertForSequenceClassification.from_pretrained("bert-base-chinese", num_labels=2)
  • 1
  • 2

报错信息如下:

requests.exceptions.ConnectTimeout: HTTPSConnectionPool(host='huggingface.co', port=443): Max retries exceeded with url: /bert-base-chinese/resolve/main/pytorch_model.bin (Caused by ConnectTimeoutError(<urllib3.connection.VerifiedHTTPSConnection object at 0x000001AAEB8F3700>, 'Connection to huggingface.co timed out. (connect timeout=10)'))
  • 1

4.1 解决思路

您的报错信息提示了连接超时问题。当您尝试从huggingface的服务器加载预训练的模型时,出现了这个问题。

以下是可能的原因及其解决方案:

  1. 网络问题:您的机器可能无法访问huggingface的服务器。这可能是由于网络速度慢、防火墙设置、网络断开或其他网络相关问题。

    解决方案

    • 请确保您的网络连接正常。
    • 试试是否可以手动访问huggingface.co网站。
    • 检查您的防火墙或代理设置,确保它们没有阻止您访问huggingface的服务器。
  2. Huggingface服务器问题:有时,由于服务器的高负载或其他问题,huggingface的服务器可能会暂时不可用。

    解决方案

    • 稍后再试。
  3. 使用代理:如果您处于一个需要代理访问外部网站的网络环境中(如在某些公司或国家),那么可能需要配置代理。

    解决方案

    • 设置Python的代理,或使用VPN。
  4. 下载模型并本地加载:如果以上方法都不起作用,您可以手动下载模型,然后从本地加载。

    解决方案

    • 手动从huggingface的模型库中下载bert-base-chinese模型。
    • 将下载的模型存放在本地目录中,然后使用from_pretrained方法加载该目录。

例如:

model = TFBertForSequenceClassification.from_pretrained("/path_to_directory/bert-base-chinese", num_labels=2)
  • 1

其中/path_to_directory/bert-base-chinese是您存放模型文件的本地目录。

4.2 解决方法

科学上网

5. Bert介绍

5.1 什么是Bert

当然可以!

BERT简介:

BERT(Bidirectional Encoder Representations from Transformers)是由Google在2018年提出的一个预训练的深度学习模型,用于自然语言处理(NLP)任务。BERT的突出特点是其双向性,即它可以同时考虑文本中的前后上下文,从而捕捉更丰富的语义信息。

BERT的核心思想:

  1. 双向性:传统的语言模型,如LSTM和GRU,是单向的,只能考虑前面的上下文或后面的上下文。BERT通过同时考虑前后上下文来捕捉更复杂的语义信息。
  2. 预训练和微调:BERT首先在大量无标签文本上进行预训练,然后可以用少量的标注数据进行微调,以适应特定的NLP任务。
  3. Transformer架构:BERT基于Transformer架构,它是一个高效的自注意力机制,可以捕捉文本中长距离的依赖关系。

BERT的预训练策略:

  1. Masked Language Model (MLM):随机遮蔽句子中的一些单词,并让模型预测这些遮蔽单词。这样,模型必须学习理解文本的上下文信息,以预测遮蔽的部分。
  2. Next Sentence Prediction (NSP):模型接收两个句子作为输入,并预测第二个句子是否是第一个句子的下一个句子。

BERT的应用:

经过预训练后的BERT模型可以被微调并应用于各种NLP任务,如文本分类、命名实体识别、问答系统等。由于BERT能够捕捉丰富的上下文信息,它在许多NLP任务中都取得了当时的最先进性能。

为什么BERT如此受欢迎?

  1. 强大的性能:BERT在多种NLP任务上都达到了当时的最先进的性能。
  2. 通用性:同一个预训练的BERT模型可以被微调并应用于多种NLP任务,无需从头开始训练。
  3. 可用性:由于Google和其他组织发布了预训练的BERT模型和相关工具,开发者可以轻松地使用BERT进行自己的NLP项目。

总结:

BERT是当前NLP领域的一个里程碑,它改变了我们如何处理和理解文本的方式。对于初学者,理解BERT及其工作原理是深入研究现代NLP的关键。希望这个简介能帮助您对BERT有一个初步的了解!

6. 其他

6.1 epoch

Epoch 1/10
61/61 [==============================] - 2293s 36s/step - loss: 0.9221 - accuracy: 0.3204
Epoch 2/10
61/61 [==============================] - 2139s 35s/step - loss: 0.6931 - accuracy: 0.3147
  • 1
  • 2
  • 3
  • 4

上面的输出是深度学习模型训练过程中的一个典型日志。这个日志显示了在训练期间的某个阶段(在这种情况下是第一个周期或“epoch”)的性能指标。下面逐一解释这些参数的含义:

  1. Epoch 1/10:

    • Epochs: 这表示当前正在进行的训练周期。一个周期意味着整个训练数据集已经被模型完整地处理了一次。
    • 1/10: 这里的“1/10”意味着模型目前正在完成第一个训练周期,总共计划进行10个这样的周期。
  2. 61/61 [==============================]:

    • 这部分显示了在当前周期中已处理的批量数与总批量数。
    • 61/61: 意味着模型已经处理了所有61个批量。这是基于您的数据集大小和batch_size决定的。(数据集大小/batch_size)
  3. 2293s 36s/step:

    • 2293s: 这是整个周期的总耗时,单位是秒。在这个例子中,完成第一个周期花费了大约2293秒。
    • 36s/step: 这表示每个批量(或“step”)的平均处理时间是36秒。步骤是训练过程中的一次迭代,每次处理一个batch_size大小的数据。
  4. loss: 0.9221和 loss: 0.6931:

    • Loss: 这是模型在训练数据上的损失函数值。损失函数衡量的是模型预测与实际标签之间的差异。
    • 0.9221: 这是当前周期结束时的平均损失值。通常,我们希望这个数值随着训练的进行而降低。
    • loss: 0.9221 和 loss: 0.6931: 损失值是一个衡量模型预测误差的指标。它表明模型的预测结果与实际值之间的差异。一般而言,训练过程中希望看到损失值逐渐减小
  5. accuracy: 0.3204和 accuracy: 0.3147:

    • Accuracy: 这是模型在训练数据上的准确率。
    • 0.3204: 表示模型的准确率约为32.04%。准确率是正确预测的样本数占总样本数的比例。
    • accuracy: 0.3204 和 accuracy: 0.3147: 这是模型在训练数据上的准确率。这个值表示模型正确预测的样本占总样本的比例。在这个例子中,准确率较低,这可能表明模型性能不是很好。

从这个日志可以看出,模型在第一个训练周期的表现。请注意,一个低准确率(如32.04%)可能意味着模型需要进一步优化,例如调整模型结构、学习率或其他训练参数。此外,2293秒(约38分钟)的训练时间表明,每个周期相对较长,这可能是由于模型的复杂性、数据集的大小、计算资源的限制或batch_size的设置。

36和2293什么关系?

上面提供的训练输出中,“36s/step” 和 “2293s” 表示的是训练过程中每步(step)和整个训练周期(epoch)的耗时。这里,“36s/step” 表示每个训练步骤平均耗时 36 秒,而 “2293s” 是整个训练周期(Epoch 1)的总耗时。让我们分析这二者之间的关系:

  • 每步耗时(Step Time): 每个训练步骤平均耗时 36 秒。
  • 步骤数量(Number of Steps): 训练输出显示每个训练周期包含 61 步。
  • 总耗时(Total Time): 整个训练周期的总耗时为 2293 秒。

要理解这二者之间的关系,我们可以将每步的耗时乘以步骤数来估算整个训练周期的耗时。具体计算公式为:

每步耗时 × 步骤数 = 总耗时 \text{每步耗时} \times \text{步骤数} = \text{总耗时} 每步耗时×步骤数=总耗时
36  秒/步 × 61  步 = 2196  秒 36 \text{ 秒/步} \times 61 \text{ 步} = 2196 \text{ 秒} 36 /×61 =2196 

计算结果是 2196 秒,这与代码提供的 2293 秒相近。这种小的差异可能是由于在训练过程中每个步骤的耗时略有不同或者其他训练相关的开销导致的。

accuracy: 0.3204 和 accuracy: 0.3147是不同批次样本计算的准确率?

是的,您的理解是正确的。在您提供的训练输出中,“accuracy: 0.3204” 和 “accuracy: 0.3147” 分别表示两个不同训练周期(epochs)结束时模型在训练数据集上的准确率。这些准确率是基于在各个周期内处理的不同批次(batches)的样本计算得出的。

让我更详细地解释一下:

  1. 训练周期(Epoch)

    • 在深度学习中,一个训练周期指的是整个训练数据集被完整地处理一次。在每个训练周期内,数据集被分成多个批次。
  2. 批次(Batch)

    • 批次是数据集的一个子集,用于在一个训练步骤中更新模型的权重。模型在每个批次上进行训练,并根据这个批次的数据更新其参数。
  3. 准确率计算

    • 在每个训练周期结束时,模型的性能(比如准确率)是基于该周期内所有批次的累积结果计算得出的。所以,“accuracy: 0.3204” 是第一个训练周期结束时的准确率,而 “accuracy: 0.3147” 是第二个训练周期结束时的准确率。
    • 这些准确率反映了模型在那个特定训练周期内对所有处理过的批次样本的平均表现。
  4. 准确率变化

    • 通常,在训练过程中,我们期望看到准确率随着时间的推移而逐渐提高,表明模型正在学习并改善其在训练数据上的性能。
    • 在您的案例中,准确率在两个训练周期之间略有下降,这可能表明模型的学习过程存在一些问题,需要调整训练策略或模型结构。

前一个epoch会影响后一个epoch的accuracy和loss吗

前一个训练周期(epoch)会影响后一个训练周期的准确率(accuracy)和损失值(loss)。

在深度学习的训练过程中,这是一个累积和连续的过程,其中每个训练周期的结果都会影响到下一个周期的初始状态。下面是一些详细的解释:

  1. 权重和参数更新

    • 在每个训练周期结束时,模型的权重和参数会根据该周期内的数据进行更新。这意味着下一个训练周期开始时,模型将使用更新后的权重和参数。
  2. 准确率和损失值的演变

    • 因为每个训练周期都使用更新后的模型参数开始,所以前一个周期的学习成果(表现为损失值和准确率的改善)会影响到后续周期的性能。
    • 理想情况下,随着训练周期的增加,模型应该在训练数据上表现出逐步提高的准确率和逐步降低的损失值。
  3. 学习的累积效应

    • 训练过程可以被视为一个学习的累积过程。每个训练周期都在前一个周期的基础上继续优化模型,从而使得模型逐步适应训练数据。
  4. 潜在的问题

    • 如果观察到准确率没有提高或损失值没有降低,或者它们的变化不符合预期(例如,准确率降低或损失值增加),这可能是过拟合、欠拟合、学习率设置不当或其他问题的迹象。

因此,是的,前一个训练周期的结果会影响到后一个周期的accuracy和loss,这是深度学习训练过程中参数更新和模型学习的自然结果。

epoch=10代表什么

在机器学习和深度学习中,epoch 是一个非常重要的概念。当您看到 epoch=10,这意味着训练算法将整个训练数据集遍历10次。每次遍历整个数据集称为一个 “epoch”。

以下是详细的解释:

  1. 数据集遍历:在每个 epoch 中,学习算法将看到并学习整个训练数据集一次。这意味着每个样本在训练过程中将被使用10次(因为有10个 epoch)。

  2. 学习过程:在每个 epoch 中,模型的参数(如神经网络中的权重)会根据数据集中的样本进行调整,以最小化损失函数,这是为了提高模型的性能和准确性。

  3. epoch 与模型性能:增加 epoch 的数量通常会提高模型的学习能力,因为模型有更多的机会学习和调整其参数。然而,太多的 epochs 可能导致过拟合,即模型在训练数据上表现很好,但在未见过的数据上表现不佳。

  4. 选择合适的 epoch 数量:确定合适的 epoch 数量通常是一个实验过程。太少可能导致模型欠拟合,而太多则可能导致过拟合。使用诸如早停(early stopping)之类的技术可以帮助确定何时停止训练,即当模型在验证集上的性能不再提高时。

总之,epoch=10 意味着训练过程将在整个数据集上重复10次,使模型有足够的机会从数据中学习并调整其参数。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/625548
推荐阅读
相关标签
  

闽ICP备14008679号