Pytorch 当列车损失减少时,验证损失增加且精度保持恒定为零的原因是什么?
我试图解决一个多类文本分类问题。由于我的项目的特殊要求,我尝试使用skorch()为sklearn管道包装pytorch。我想做的是用我的数据集对Huggingface()中经过预训练的BERT版本进行微调。据我所知,我已尝试按照skorch的指示,如何输入数据、构建模型等。在培训期间,列车损失减少,直到第8个纪元开始波动,同时,验证损失从一开始就增加,验证精度保持不变为零。我的管道设置是Pytorch 当列车损失减少时,验证损失增加且精度保持恒定为零的原因是什么?,pytorch,text-classification,multiclass-classification,bert-language-model,skorch,Pytorch,Text Classification,Multiclass Classification,Bert Language Model,Skorch,我试图解决一个多类文本分类问题。由于我的项目的特殊要求,我尝试使用skorch()为sklearn管道包装pytorch。我想做的是用我的数据集对Huggingface()中经过预训练的BERT版本进行微调。据我所知,我已尝试按照skorch的指示,如何输入数据、构建模型等。在培训期间,列车损失减少,直到第8个纪元开始波动,同时,验证损失从一开始就增加,验证精度保持不变为零。我的管道设置是 from sklearn.pipeline import Pipeline pipel
from sklearn.pipeline import Pipeline
pipeline = Pipeline(
[
("tokenizer", Tokenizer()),
("classifier", _get_new_transformer())
]
在其中,我使用一个标记器类来预处理我的数据集,为BERT标记它并创建注意掩码。看起来像这样
import torch
from transformers import AutoTokenizer, AutoModel
from torch import nn
import torch.nn.functional as F
from sklearn.base import BaseEstimator, TransformerMixin
from tqdm import tqdm
import numpy as np
class Tokenizer(BaseEstimator, TransformerMixin):
def __init__(self):
super(Tokenizer, self).__init__()
self.tokenizer = AutoTokenizer.from_pretrained(/path/to/model)
def _tokenize(self, X, y=None):
tokenized = self.tokenizer.encode_plus(X, max_length=20, add_special_tokens=True, pad_to_max_length=True)
tokenized_text = tokenized['input_ids']
attention_mask = tokenized['attention_mask']
return np.array(tokenized_text), np.array(attention_mask)
def fit(self, X, y=None):
return self
def transform(self, X, y=None):
word_tokens, attention_tokens = np.array([self._tokenize(string)[0] for string in tqdm(X)]), \
np.array([self._tokenize(string)[1] for string in tqdm(X)])
X = word_tokens, attention_tokens
return X
def fit_transform(self, X, y=None, **fit_params):
self = self.fit(X, y)
return self.transform(X, y)
然后,我初始化我想要微调的模型
class Transformer(nn.Module):
def __init__(self, num_labels=213, dropout_proba=.1):
super(Transformer, self).__init__()
self.num_labels = num_labels
self.model = AutoModel.from_pretrained(/path/to/model)
self.dropout = torch.nn.Dropout(dropout_proba)
self.classifier = torch.nn.Linear(768, num_labels)
def forward(self, X, **kwargs):
X_tokenized, attention_mask = torch.stack([x.unsqueeze(0) for x in X[0]]),\
torch.stack([x.unsqueeze(0) for x in X[1]])
_, X = self.model(X_tokenized.squeeze(), attention_mask.squeeze())
X = F.relu(X)
X = self.dropout(X)
X = self.classifier(X)
return X
我初始化模型并使用skorch创建分类器,如下所示
from skorch import NeuralNetClassifier
from skorch.dataset import CVSplit
from skorch.callbacks import ProgressBar
import torch
from transformers import AdamW
def _get_new_transformer() -> NeuralNetClassifier:
transformer = Transformer()
net = NeuralNetClassifier(
transformer,
lr=2e-5,
max_epochs=10,
criterion=torch.nn.CrossEntropyLoss,
optimizer=AdamW,
callbacks=[ProgressBar(postfix_keys=['train_loss', 'valid_loss'])],
train_split=CVSplit(cv=2, random_state=0)
)
return net
我用的是那种合适的
pipeline.fit(X=dataset.training_samples, y=dataset.training_labels)
其中,我的训练样本是字符串列表,我的标签是包含每个类的索引的数组,正如pytorch所要求的那样
这是发生了什么的一个例子
我试着只保持训练完全连接的层,而不是伯特,但我又遇到了同样的问题。在训练过程结束后,我还测试了训练的准确度,仅为0,16%。我将非常感谢任何关于如何解决我的问题的建议或见解!我对斯科奇很陌生,对派托克还不太适应,我相信我错过了一些非常简单的东西。提前非常感谢