赞
踩
使用pytorch的框架搭建一个简单多分类神经网络模型,解决水果分类问题。本文包括对数据格式的转换、网络构架、模型训练、预测,并未进行后续的优化,目的在于对流程的熟悉。
从原始数据到标准格式的一系列处理
#导入包 import pandas as pd import sklearn from sklearn.model_selection import train_test_split from sklearn.feature_selection import SelectKBest, chi2 from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder,MinMaxScaler, StandardScaler import torch.nn as nn import torch.nn.functional as F import torch from torch import optim from torch.utils.data import Dataset,DataLoader # 加载数据 data=pd.read_csv('/Users/guidongzhang/Desktop/Data Mining/fruit/Date_Fruit_Datasets.csv') # 数据标准化 def normalize(x): scaler = StandardScaler() return scaler.fit_transform(x)#fit_transform 是fit和transform的结合 # 特征选择 def selectFeatures(x,y,n): select=SelectKBest(k=n)#chi2 return select.fit_transform(x,y) # 提取特征和标签 y=data['Class'].values X=data.drop('Class',1) X=normalize(X) SelectedFeatures=selectFeatures(X,y,10) # target one-hot编码 encoder = OneHotEncoder() encoder.fit(y.reshape(len(y), 1)) y = encoder.transform(y.reshape(len(y), 1)) y=y.toarray() # 分隔训练集测试集 x_train,x_test,y_train,y_test=train_test_split(SelectedFeatures,y,test_size=0.2) # 转换为tensor张量 x_train=torch.tensor(x_train,dtype=torch.float) x_test=torch.tensor(x_test,dtype=torch.float) y_train=torch.tensor(y_train,dtype=torch.float) y_test=torch.tensor(y_test,dtype=torch.float)
下面要进行一步重要的转换,为了训练的方便,我们先要将数据转化为torch.utils.data
中的Dataset
类,再转化为DataLoader
类。
首先创建一个Dataset
的子类,必须包含__init__
__getitem__
__len__
。其中__getitem__
的作用是给定index能输出对应的特征及标签, __len__
输出数据的长度。DataLoader
将Dataset
对象或自定义数据类的对象封装成一个迭代器,同时可以实现多进程、shuffle、不同采样策略,数据校对等等处理过程。
由于我的数据并非图像数据,流程做了一定简化,详细查看Pytorch构建数据集。
# 构建Dataset数据集 class MyDataset(Dataset):#需要继承torch.utils.data.Dataset def __init__(self,feature,target): super(MyDataset, self).__init__() self.feature =feature self.target = target def __getitem__(self,index): item=self.feature[index] label=self.target[index] return item,label def __len__(self): return len(self.feature) # 封装成DataLoader对象 bs=64 train_data=MyDataset(x_train,y_train) train_data=DataLoader(train_data, batch_size=bs, shuffle=True)
典型的卷积神经网络通常由以下三种层结构共同组成:卷积层(Convolution)、下采样池化层(Pooling)、全连接层(Fully connected),以及激活函数。由于我们的例子是简单多分类问题,不需要卷积和池化操作,使用线性全连接层和非线性激活函数即可。
在这里使用两层全连接层,第一层的激活函数使用ReLU,第二层使用Sigmoid。
class Model(nn.Module):#继承nn.Module
def __init__(self,in_features,out_features):
super().__init__()
self.linear1 = nn.Linear(in_features, 10, bias = True)
self.linear2 = nn.Linear(10, out_features, bias = True)
self.relu=nn.ReLU()
self.sig=nn.Sigmoid()
def forward(self, x):
s=self.linear1(x)
s=self.relu(s)
s=self.linear2(s)
s=self.sig(s)
return s
打印出的网络结构:
Model(
(linear1): Linear(in_features=20, out_features=10, bias=True)
(relu): ReLU()
(linear2): Linear(in_features=10, out_features=7, bias=True)
(sig): Sigmoid()
)
模型训练分为几个流程:
损失函数使用平均绝对误差(MAE),优化算法使用随机梯度下降(SGD)。我们将这个流程封装起来。batchdata
为dataloader
类数据,lr
为学习率,gamma
为优化算法参数,epochs
为遍历次数。
def fit(net, batchdata, lr, gamma, epochs): # 损失函数 criterion = nn.L1Loss() # 优化算法 opt = optim.SGD(net.parameters(), lr = lr, momentum = gamma) # 监视进度 samples = 0 # 监视准确度 corrects = 0 # 全数据训练几次 for epoch in range(epochs): # 对每个batch进行训练 for batch_idx, (x,y) in enumerate(batchdata): # 正向传播 sigma = net.forward(x) # 计算损失 loss = criterion(sigma, y) # 反向传播 loss.backward() # 更新梯度 opt.step() # 梯度清零 opt.zero_grad() # 监视进度:每训练一个batch,模型见过的数据就会增加x.shape[0] samples += x.shape[0] #每200个batch和最后结束时,打印模型的进度 if (batch_idx + 1) % 200 == 0 or batch_idx == (len(batchdata) - 1): # 监督模型进度 print("Epoch{}:[{}/{} {: .0f}%], Loss:{:.6f} ".format( epoch + 1 , samples , epochs*len(batchdata.dataset) , 100*samples/(epochs*len(batchdata.dataset)) , loss.data.item()))
设置参数并开始训练:
# 设置随机种子 torch.manual_seed(51) # 实例化模型 net = Model(10,7) # 学习率 lr = 0.15 # 优化算法参数 gamma = 0.8 # 每次小批次训练个数 bs = 64 # 整体数据循环次数 epochs = 50 # 生成数据 train_data=MyDataset(x_train,y_train) train_data=DataLoader(train_data, batch_size=bs, shuffle=True) # 训练模型 fit(net, train_data, lr, gamma, epochs)
打印进度及损失:
预测的方法就是将待预测数据输入训练好的模型,进行向前传播,net.forward(x_test)
。我们有七个种类,之前的one-hot编码中,将每一个种类用一维、长度为7的向量表示,对应的位置为1,其余位置为0。
输出的结果也是这样
7
×
1
7\times1
7×1的向量,我们选取其最大数对应的位置作为预测结果,计算准确率。
# 计算准确率的函数
def Accuracy(l1,l2):
l1,l2=np.array(l1),np.array(l2)
s=np.count_nonzero(l1-l2,axis=None)/len(l1-l2)
return 1-s
最终我们模型的准确率达到了0.62。
本文提供了用pytorch构建神经网络解决实际问题的一个案例,介绍了pytorch使用的大致流程,可以作为学习的参考。如果想进一步了解神经网络的原理及pytorch使用的更多细节,建议观看视频系统学习。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。