本文节选自笔者承接某外包平台订单时设计和编写的方案和代码,供广大爱好者和从业者参考,如需咨询和定制相关方案和模型,欢迎评论区讨论或私信联系。
主动学习,即在拥有少部分监督数据的情况下,主动的去选择一部分对训练模型有较大提高的未标注数据,然后对选择出来的数据进行标注,标注后加入到训练集进行训练。为什么这么做的,我们把数据都标注一下不行吗?当然可以,但是标注是要时间和金钱的,特别是对于科研数据、工程数据来说,我们希望选择更有助于模型提高的数据先进行标注。如下图所示:
在这个方案针对的岩土力学数据中,前两个通道是土的力学参数,是随机场生成的,第三个数据是桩位,每条数据的形状为3信道40*70的形式,这形式彷佛一个有三种颜色的40*70大小的图片,有标注数据共2000+条,无标记数据4000+条。
PyTorch是一个开源的Python机器学习库,基于Torch,用于自然语言处理等应用程序。由Facebook人工智能研究院(FAIR)基于Torch推出。它是一个基于Python的可续计算包,提供两个高级功能:1、具有强大的GPU加速的张量计算(如NumPy)。2、包含自动求导系统的深度神经网络。
用另外一个模型来学习当前模型的损失,这是一个很有创新的想法,而且非常有用。既然我们选择数据的时候没有标签(未打标签),那么是不是可以先选择出预测较差的数据进行打标签。这时候loss确实是一个可以用来做这种选择的东西。当loss较大的时候说明和真实标签的差异性很大,loss较小则差异较小。其实最终我们是要对未打标签的数据进行排序,先是模型较难预测的,然后再是较好预测的。
Kaggle Notebook 在线环境 2023.1.6版
import scipy.io as sio
import os
import pandas as pd
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
load_data = os.path.join(os.getcwd(),'/kaggle/input/mat-train/traindata.mat')
data = sio.loadmat(load_data) #a dict
features = data['input_database']
label = data['output_database']
features = features.T
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# Assuming that we are on a CUDA machine, this should print a CUDA device:
print(device)
x = torch.from_numpy(features).float().to(device)
y = torch.from_numpy(label).float().to(device)
class Cnn(nn.Module):
def __init__(self):
super(Cnn, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=10, kernel_size=3, stride=1), #卷积层
nn.ReLU(True),
nn.MaxPool2d(kernel_size=2, stride=1),#最大池化层
nn.Conv2d(in_channels=10, out_channels=10, kernel_size=3, stride=1),
nn.ReLU(True),
nn.MaxPool2d(kernel_size=2, stride=1),
nn.Flatten() # 展平操作,为了与全连接层匹配
)
self.fc = nn.Sequential(
nn.Linear(21760,100), #线性层
nn.ReLU(inplace=True), # relu激活函数
nn.Dropout(0.1),
nn.Linear(100, 1),
nn.ReLU(inplace=True),
)
def forward(self, x): #
out = self.conv(x)
# out = out.view(out.size(0), 10 * 25 * 25)
# print(out.shape)
out = self.fc(out)
# print(out.shape)
return out
网络选择两层卷积+两层池化层+全连接,激活函数选择Relu,全连接中添加Dropout层。
#把模型装到CUDA显存
net = Cnn().to(device)
#优化器选用SGD(随机梯度下降法)进行学习率优化,可换Adam、Adamax、ASGD等
optimizer = torch.optim.Adamax(net.parameters(),lr = 0.01)
#使用MSE作为loss,可以换MAE、R2等
loss_func = torch.nn.MSELoss()
losslist = []
#此处选择训练轮数
epochs = 1000
#训练外循环
for t in range(epochs):
#用当前网络进行预测
prediction = net(x)
#计算loss
loss = loss_func(prediction,y)
#加入loss列表
losslist.append(float(loss.cpu().detach().numpy()))
#优化器梯度重置
optimizer.zero_grad()
#反向传播
loss.backward()
#优化器迭代
optimizer.step()
#此处用于查看loss
if t%100 == 0:
print('loss:',loss.cpu().detach().numpy())
import seaborn as sns
sns.lineplot(y=losslist,x=range(epochs))
#将模型用于预测
net.eval()
#预测全部数据点
outputs=net(x)
List = []
#计算并储存全部数据点loss,从而获得哪个数据点的类型需要更多标注
for i in range(2982):
value = loss_func(outputs[i],y[i]).cpu().detach().numpy()
List.append(float(value))
Loss = pd.DataFrame(List)
Loss = Loss.to_numpy()
Loss.shape
x = torch.from_numpy(features).float().to(device)
#此时将Label换成Loss
y = torch.from_numpy(Loss).float().to(device)
进行对loss的回归训练
#把模型装到CUDA显存
net = Cnn().to(device)
#优化器选用SGD(随机梯度下降法)进行学习率优化,可换Adam、Adamax、ASGD等
optimizer = torch.optim.SGD(net.parameters(),lr = 0.1)
#使用MSE作为loss,可以换MAE、R2等
loss_func = torch.nn.MSELoss()
losslist = []
#此处选择训练轮数
epochs = 1000
#训练外循环
for t in range(epochs):
#用当前网络进行预测
prediction = net(x)
#计算loss
loss = loss_func(prediction,y)
#加入loss列表
losslist.append(float(loss.cpu().detach().numpy()))
#优化器梯度重置
optimizer.zero_grad()
#反向传播
loss.backward()
#优化器迭代
optimizer.step()
#此处用于查看loss
if t%100 == 0:
print('loss:',loss.cpu().detach().numpy())
load_data = os.path.join(os.getcwd(),'/kaggle/input/mat-train/test_input.mat')
data = sio.loadmat(load_data) #a dict
features = data['input_database']
features = features.T
features.shape
features_test = features.reshape(4694,3*70*40)
test = pd.DataFrame(features_test)
test.to_csv('active_test.csv')
outputs_test=net(x).cpu().detach().numpy()
outputs_test = pd.DataFrame(outputs_test)
outputs_test.to_csv('prediction_Loss.csv')
监督学习问题中,存在标记成本较为昂贵且标记难以大量获取的问题。 针对一些特定任务,只有行业专家才能为样本做上准确标记。在此问题背景下,主动学习(Active Learning, AL)尝试通过选择性的标记较少数据而训练出表现较好的模型。主动学习已经是一个较为成熟的技术,已经有很多研究工作将其应用于不同学科和领域,本文仅从最简单方法出发,作为示例。