Pytorch深度学习项目–基于基因表达量的细胞分类
实现数据打包
首先导入包
import torch
from torch.utils.data import Dataset
import numpy as np
定义类
class human_mouse(Dataset):#继承父类Dataset
def __init__(self,root,train=True):#初始内置函数,实例化时就会加载,self代指实例化对象,root与train都是自定义形参。
super(human_mouse,self).__init__()#继承并执行human_mouse的父类的__init__
self.train = train
self.labels =['BETA','DELTA','ACTIVATED_STELLATE','DUCTAL','ALPHA','GAMMA','ENDOTHELIAL','QUIESCENT_STELLATE','MACROPHAGE','SCHWANN','T_CELL']#标签
self.labels2idx = dict([ (label,i) for i,label in enumerate(self.labels)])
#enumerata函数用于输入一个序列,返回下标,元素。dict函数二元组字典化,例:dict([(0,1)]),>>>{0: 1}
self.X,self.y=self.load_data(root,train)#load_data在后面
self.root = os.path.expanduser(root)#os.path.expanduser会将目录前的~替换为账户目录,例:os.path.expanduser('~/.config/'),返回'/home/kwsy/.config/',其中kwsy为你的账户名
def __getitem__(self, index):#继承了Dataset类,需要重写__getitem__与__len__方法
return (self.X[index],self.y[index])#__getitem__很重要,依据它返回的数据来确定,输入数据集与标签数据集
def __len__(self):#用于计算输入数据集的样本数量
return len(self.X)
自定义函数,用于获取与处理数据
def load_data(self,root,train):
if train:#获取human的数据
data_path=os.path.join(root, "human_data.csv")#os.path.join函数实现字符串拼接
human_data=pd.read_csv(data_path)#使用panda模块的pd.read_csv读取csv表格返回'pandas.core.frame.DataFrame'类数据
human_data=human_data.drop('Unnamed: 0',1)#删除‘Unnamed: 0’的列(其中1就指定‘列’)
rows = human_data.T.values#转置后取出里面的值,返回一个大numpu数组
data_path=os.path.join(root, "label_human.csv")
label_human=pd.read_csv(data_path)
label_human=label_human.loc[:,'x']#通过行,列的名字获取值,返回‘pandas.core.series.Series’类
label=label_human.values
else:#获取mouse的数据
data_path=os.path.join(root, "mouse_data.csv")
mouse_data=pd.read_csv(data_path)
mouse_data=mouse_data.drop('Unnamed: 0',1)
rows = mouse_data.T.values
data_path=os.path.join(root, "label_mouse.csv")
label_mouse=pd.read_csv(data_path)
label_mouse=label_mouse.loc[:,'x']
label=label_mouse.values
n_datas = len(rows)
X = np.zeros((n_datas, 12022), dtype=np.float32)
y = np.zeros(n_datas, dtype=np.int32)
for i, row in enumerate(rows):
X[i, :] = list(map(float, row[:]))#将列表进行float映射,返回经过float(x)函数映射后的列表
y[i]= self.labels2idx[label[i]]#将字符标签转化为int数字
X = torch.from_numpy(X).type(torch.FloatTensor)#将numpy数组转化为Tensor
y = torch.from_numpy(y).type(torch.LongTensor)
return X,y
建立神经网络结构
class module(nn.Module):#继承父类Module
def __init__(self):
super(module,self).__init__()
self.lstm = nn.LSTM(1, 64,batch_first=True)#nn.Lstm输入参数最要需要(特征维度大小,隐层大小)注意:默认input_size=[序列长度,样本数,特征个数],而这里的batch_first=True,会改变网络结构的input_size为[序列长度,样本数,特征个数]
self.dense = nn.Linear(64,11)#全连接层,输入参数为(输入维度,输出维度)
def forward(self, x):#神经网络计算,x为输入数据集
result,_= self.lstm(x)#因为采用的是nn.Lstm,返回的是(output,(h,c)),且output_size=[序列长度,样本数,隐层个数X方向个数(1 or 2)],也就是说nn.Lstm的output是包含了所有每一步时间序列的输出
result = self.dense(result[:,-1,:])#这里取最后一个时间步的输出
return result
实例化模型与Dataset的对像并打包到DataLoader
Coder = module()#实例化模型对象
optimizer = torch.optim.Adam(Coder.parameters(),lr=0.001)#定义优化器为Adam,输入形参(模型的结构与权重,学习率=0.001)
loss_func = nn.CrossEntropyLoss()#pytorch中的交叉熵损失函数,它会将输出进行softmax然后全部取对数,虽然网络最后每个样本输出11维(表示11个种类),但是标签数据集得是一维int数组,每一个int数代表对应样本的种类标签(0~10),交叉熵函数会根据标签从每个样本的11维输出里面取对应标签数下标的值,最后将这些值取负平均。
train_set=human_mouse('./', train=True)#实例化数据集对象
BATCH_SIZE = 16#一批的数量
train_loader = torch.utils.data.DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True,drop_last=True)#打包到train_loader,形参中的shuffle代表是否打乱样本顺序,drop_last代表是否将最后不够BATCH_SIZE的样本不训练。
训练数据
for epoch in range(300):
correct = 0
for batch_idx,(X_batch,y_batch) in enumerate(train_loader):#取出批次数与对应的输入输出数据样本
optimizer.zero_grad()
output = Coder.forward(X_batch) #将输出传入神经网络
loss = loss_func(output,y_batch)#计算损失值
loss.backward()#loss对各个权重参数求导
optimizer.step()#更新权重
'''计算准确度'''
predicted = torch.max(output.data,1)[1]#torch.max(Tensor数组,axis),返回(最大数下标数组,最大数数组)
correct += (predicted == y_batch).sum()
'''打印迭代信息'''
if batch_idx % 470 == 0:
print('Epoch :{}[{}/{}({:.0f}%)] Loss:{:.6f} Accuracy:{:.3f}'.format(epoch,batch_idx * len(X_batch),
len(train_loader.dataset),
100.*batch_idx / len(train_loader),
loss.data.item(),
float(correct)/(float(BATCH_SIZE)*(batch_idx+1))))
保存模型(网络结构+参数)
torch.save(Coder, 'model.pt')
读取模型
Coder_new = torch.load('model.pt')
output = Coder_new(input)