加载数据集
- 之前的都是采用直接读取整个数据到内存中,但要是数据集很大,就不能这样做了,这就需要一次读取一部分数据,即采用Mini-Batch
- Epoch:在所有数据集上完成了一次前馈和反馈,叫作一次Epoch
- Batch-Size:一次训练的样本数量
- Iteration:训练一次所有数据集需要运行的Batch-Size数量,例如一共10000个数据集,Batch-Size设置为1000,则Iteration为10000/1000=10
#Training cycle
for epoch in range(training_epochs):
#Loop over all batches
for i in range(total_batch):
Cell In[1], line 4
for i in range(total_batch):
^
SyntaxError: incomplete input
加载数据的具体代码
import torch
from torch.utils.data import Dataset # Dataset是一个抽象类,只能被继承,不能被实例化
from torch.utils.data import DataLoader # Pytorch中用来加载数据的类
class DiabetesDataset(Dataset): # 继承Dataset类
def __init__(self):
pass
def __getitem__(self,index): # 魔法函数,获取数据标签
pass
def __len__(self): # 魔法函数,获取数据集长度
pass
dataset=DiabetesDataset() # 实例化DiabetesDataset类
train_loader=DataLoader(dataset=dataset,
batch_size=32,
shuffile=True, # 是否打乱,True则打乱数据集
num_workers=2) # 线程数,CPU核心多的可以多开几个线程
多线程问题在Windows和Linux中的不同
Windows的多线程用的是spawn
,而Linux用的是fork
,因此直接像上面那么写会报错,应该写成
if __name__=='__main__':
for epoch in range(100):
for i, data in enumerate(train_loader,0):
完整代码
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
class DiabetesDataset(Dataset):
def __init__(self, filepath):
xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32) #大部分游戏显卡都只有float类型,所以这里也采用float类型
self.len = xy.shape[0] #纵向维度
self.x_data = torch.from_numpy(xy[:, :-1]) #第一个`:`表示所有行,第二个`:-1`表示从第一列开始到最后一个列之前结束(不会包括最后一列),因为最后一列是y值
self.y_data = torch.from_numpy(xy[:, [-1]]) #以矩阵形式(即原来是矩阵的列,取出后还是)取出最后一列
def __getitem__(self, index):
return self.x_data[index], self.y_data[index]
def __len__(self):
return self.len
dataset = DiabetesDataset('diabetes.csv.gz')
train_loader = DataLoader(dataset=dataset,
batch_size=32,
shuffle=True, #打乱
num_workers=2) #双线程
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
self.linear1 = torch.nn.Linear(8, 6) # 8 → 6
self.linear2 = torch.nn.Linear(6, 4) # 6 → 4
self.linear3 = torch.nn.Linear(4, 1) # 4 → 1
self.sigmoid = torch.nn.Sigmoid() # 激活函数,采用逻辑斯蒂回归
def forward(self, x):
# 这里的变量命名不要命为o1 o2 o3这种,到时候写错了都不好改BUG,直接统一用一个字母就行,就像下面都用的是x
x = self.sigmoid(self.linear1(x)) #在每次降维后都进行一次逻辑斯蒂回归,即进行一次非线性变换
x = self.sigmoid(self.linear2(x))
x = self.sigmoid(self.linear3(x))
return x
model = Model()
criterion = torch.nn.BCELoss(size_average=True) #BCE损失函数
optimizer = torch.optim.SGD(model.parameters(), lr=0.01) #优化器,学习率定为0.01
if __name__ == '__main__': #多进程时一定要加这一行,把含有多进程的程序放在里面,不然运行时会报错
for epoch in range(100): #100个Epoch
for i, data in enumerate(train_loader, start=0): #enumerate()的作用是同时列出数据和数据下标
#准备数据集
inputs, labels = data
#前馈
y_pred = model(inputs)
loss = criterion(y_pred, labels)
print(epoch, i, loss.item())
#反馈
optimizer.zero_grad()
loss.backward()
#更新
optimizer.step()