我最近在看半监督方面的知识,最近摸了一个pi model方式进行训练,采用的数据集是minst。其中有标签数据为100 无标签数据为49900 测试数据为10000,batch size为100.
关键训练代码如下:
for current_epoch in range(epochs):
#损失函数
agg_cost = 0.
agg_supervised_cost = 0.
agg_unsupervised_cost = 0.
num_batches = 0
pimodel.train()#训练
ind_labelled = 0
ind_limit = np.ceil(float(train_labelled_images.shape[0]) / batch_size) #1
for batch_idx, (unlabelled_images, unlabelled_labels) in enumerate(unlabelled_loader):
if ind_labelled == ind_limit:
randomize = np.arange(train_labelled_images.shape[0])
np.random.shuffle(randomize)
train_labelled_images = train_labelled_images[randomize]
train_labelled_labels = train_labelled_labels[randomize]
ind_labelled = 0
# TODO: Verify whether labelled examples are used for calculating unsupervised loss.
ind_labelled += 1
batch_train_labelled_images = torch.FloatTensor(train_labelled_images)
batch_train_labelled_labels = torch.LongTensor(train_labelled_labels)
labelled_data = Variable(batch_train_labelled_images, requires_grad=False)#有标签数据
labelled_target = Variable(batch_train_labelled_labels, requires_grad=False)#有标签数据的标签,用于交叉熵损失
unlabelled_data = Variable(unlabelled_images)#无标签数据,用于一致性损失
optimizer.zero_grad()
# do a noisy pass for ldata
noise1 = GaussianNoise(batch_size)
noise2 = GaussianNoise(batch_size)
noise3 = GaussianNoise(batch_size)
labelled_data = noise1(labelled_data)
output_noise_labelled = pimodel.forward(labelled_data)#通过了加了noise的label预测结果
output_unlabelled_1 = pimodel.forward(noise2(unlabelled_data)) #获取噪声1的输出预测
output_unlabelled_2 = pimodel.forward(noise3(unlabelled_data)) # 获取噪声2的输出预测
cost_supervised = loss_supervised.forward(output_noise_labelled, labelled_target)# 有监督损失
cost_unsupervised = 0.#无监督
cost_unsupervised += loss_unsupervised.forward(output_unlabelled_1, output_unlabelled_2)
# backprop
if current_epoch < 3: gama = 0.1
if 3 <= current_epoch < 5: gama = 1
if 5 <= current_epoch < 6: gama = 10
if 6 < current_epoch < 10: gama = 1000
cost = cost_supervised + gama * cost_unsupervised
cost.backward()
optimizer.step()
agg_cost += cost.item()
agg_supervised_cost += cost_supervised.item()
agg_unsupervised_cost += cost_unsupervised.item()
num_batches += 1
if ind_labelled == ind_limit:
# Evaluation
pimodel.eval()
evaluate_(pimodel, validation_loader, current_epoch,
agg_cost / num_batches,
agg_supervised_cost / num_batches,
agg_unsupervised_cost / num_batches,
args)
pimodel.train()
训练时 半监督方式下在第一个epoch就达到了88%的准确率,但是后面随着训练次数增加,测试准确率越来越低。
Epoch: 1 Total Cost: 0.2898 Supervised Cost: 0.2106 Unsupervised Cost: 0.7919 Validation Accuracy: 0.8808
Epoch: 10 Total Cost: 2.3026 Supervised Cost: 2.3026 Unsupervised Cost: 0.0000 Validation Accuracy: 0.0998
而我做对照试验时候,即仅用100label数据进行有监督训练,那么在10个epochs后达到87%左右的准确率,结果如下
Epoch: 10 Total Cost: 0.0030 Supervised Cost: 0.0030 Unsupervised Cost: 8458.7694 Validation Accuracy: 0.8712
我的问题就是为什么我的模型性能越来越差,我的理解为半监督的方式可以增强模型的决策范围,但事实上并非如此。
另外,深度学习的凡是就是使得loss接近0,在有监督方式下最后我的一致性损失并非为0,这是否意味着这一部分在我的训练中起到了阻碍作用。
造成原因:
过拟合:过拟合是指模型在训练数据上表现很好,但在测试数据上表现较差。这可能是由于模型过于复杂或训练数据太少导致的。在半监督训练中,如果模型在无标签数据上过于依赖训练数据,就可能会导致过拟合。
标签噪声:标签噪声是指有标签数据中存在错误或噪声。如果标签噪声比较严重,那么模型在训练过程中可能会被误导,从而导致在测试数据上的表现较差。
数据分布不均衡:在半监督训练中,如果无标签数据和有标签数据的分布不同,就可能会导致模型在测试数据上的表现较差
可以试下以下方法:
使用更多的有标签数据:增加有标签数据的数量可以减少过拟合的问题,并提高模型的性能。
使用无监督学习算法:无监督学习算法可以帮助模型学习无标签数据的特征,从而减少对有标签数据的依赖。
使用噪声处理技术:噪声处理技术可以帮助模型处理标签噪声,例如使用标签传播技术或使用噪声自编码器。
调整模型复杂度:调整模型的复杂度可以避免模型过拟合,例如使用正则化或减少模型的参数数量。
使用数据增强技术:数据增强技术可以增加数据的多样性,从而减少数据分布不均衡的问题