简单线性回归问题
import torch
# 数据集:(1, 2), (2, 4), (3, 6)
x_data = torch.Tensor([[1.0], [2.0], [3.0]]) # 3×1列矩阵
y_data = torch.Tensor([[2.0], [4.0], [6.0]])
# 定义线性网络结构
class LinearModel(torch.nn.Module):
# 构造函数
def __init__(self):
# 调用父类的构造函数,形式固定,记住就行
super(LinearModel, self).__init__()
# torch.nn.Linear(每一个输入样本的维数, 每一个输入样本的维数, bias=True)。继承自Module,也可以进行反向传播
self.linear = torch.nn.Linear(1, 1)
# 前向传播时执行的计算
# 用Module构造的对象会自动构建计算图,不需要写backward
def forward(self, x):
# 运算符()重载
y_pred = self.linear(x)
return y_pred
model = LinearModel()
# MSELoss同样继承于Module
# reduction='sum'表示不求1/N
# reduction='mean'表示求1/N
criterion = torch.nn.MSELoss(reduction='sum')
# parameters()会自动寻找modules所有成员中的权重(已标记require_grad的变量)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
#【train】
for epoch in range(100):
# 预测过程
y_pred = model(x_data)
# 构造好loss层后,就会自动生成计算图,可以自动求导
loss = criterion(y_pred, y_data)
# 需要加item(),否则输出的是Tensor格式
print(epoch, loss.item())
# 在反向传播之前,需要先梯度归零
optimizer.zero_grad()
# 反向传播
loss.backward()
# 更新
optimizer.step()
print('w = ', model.linear.weight.item())
print('b = ', model.linear.bias.item())
# 【test】
x_test = torch.Tensor([[4.0]])
y_test = model(x_test)
print('y_pred = ', y_test.data)
加载数据集模板:
# Dataset是抽象类,不能实例化。由Dataset继承出的类可以实例化。
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
# Dataset是抽象类,不能实例化。由Dataset继承出的类可以实例化。
class DiabetesDataset(Dataset):
# 初始化
def __init__(self):
pass
# 目标:通过dataset[index]可以实现索引
def __getitem__(self, index):
pass
# 目标:通过len(dataset)可以返回长度
def __len__(self):
pass
# 实例化
dataset = DiabetesDataset()
# 初始化loader
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)
回归示例(加载自己数据集):
import torch
import numpy as np
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
# xy = np.loadtxt('./diabetes.csv.gz', delimiter=',', dtype=np.float32)
# x_data = torch.from_numpy(xy[:, :-1])
# y_data = torch.from_numpy(xy[:, [-1]])
# Dataset是抽象类,不能实例化。由Dataset继承出的类可以实例化。
class DiabetesDataset(Dataset):
# 初始化
def __init__(self, filepath):
xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32)
self.len = xy.shape[0]
self.x_data = torch.from_numpy(xy[:, :-1])
self.y_data = torch.from_numpy(xy[:, [-1]])
# 目标:通过dataset[index]可以实现索引
def __getitem__(self, index):
return self.x_data[index], self.y_data[index]
# 目标:通过len(dataset)可以返回长度
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, 20)
self.linear2 = torch.nn.Linear(20, 1)
self.sigmoid = torch.nn.Sigmoid()
def forward(self, x):
x = self.sigmoid(self.linear1(x))
x = self.sigmoid(self.linear2(x))
return x
model = Model()
# BCE: Binary Cross Entrophy
# reduction='sum'表示不求1/N
# reduction='mean'表示求1/N
criterion = torch.nn.BCELoss(reduction='mean')
# parameters()会自动寻找modules所有成员中的权重(已标记require_grad的变量)
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
# 在Windows编译需要将使用loader的地方封装在函数内,否则会报错。Ubuntu没有这个问题。
# 记住把epoch循环放在main函数内即可
if __name__ == '__main__':
#【train】
for epoch in range(100):
# 0表示从train_loader的指定索引0开始
for i, data in enumerate(train_loader, 0):
# 1. 准备数据
inputs, labels = data
# 2. 前向传播
y_pred = model(inputs)
# 构造好loss层后,就会自动生成计算图,可以自动求导
loss = criterion(y_pred, labels)
# 需要加item(),否则输出的是Tensor格式
print(epoch, loss.item())
# 3. 反向传播
# 在反向传播之前,需要先梯度归零
optimizer.zero_grad()
loss.backward()
# 4. 更新
optimizer.step()
softmax回归示例(MNIST数据集)
import torch
import torchvision
from torchvision import transforms
from torch.utils.data import DataLoader
transform = transforms.Compose([
# 将PIL图像H*W*C转为torch的C*H*W格式
transforms.ToTensor(),
# 归一化,均值和标准差(这里的数值是根据数据集算出来的)
transforms.Normalize((0.1307, ), (0.3081, ))
])
# 下载MNIST数据集
train_set = torchvision.datasets.MNIST(root='./dataset/mnist', train=True, transform=transform, download=True)
test_set = torchvision.datasets.MNIST(root='./dataset/mnist', train=False, transform=transform, download=True)
train_loader = DataLoader(dataset=train_set, batch_size=64, shuffle=True, num_workers=2)
test_loader = DataLoader(dataset=test_set, batch_size=64, shuffle=True, num_workers=2)
# 定义模型
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
self.linear1 = torch.nn.Linear(784, 512)
self.linear2 = torch.nn.Linear(512, 256)
self.linear3 = torch.nn.Linear(256, 128)
self.linear4 = torch.nn.Linear(128, 64)
self.linear5 = torch.nn.Linear(64, 10)
self.activate = torch.nn.ReLU()
def forward(self, x):
# x.view(x.shape[0], -1)表示将batch_size*1*28*28格式转为batch_size*784格式
x = self.activate(self.linear1(x.view(x.shape[0], -1)))
x = self.activate(self.linear2(x))
x = self.activate(self.linear3(x))
x = self.activate(self.linear4(x))
x = self.activate(self.linear5(x))
return x
model = Model()
# reduction='sum'表示不求1/N
# reduction='mean'表示求1/N
criterion = torch.nn.CrossEntropyLoss(reduction='mean')
# parameters()会自动寻找modules所有成员中的权重(已标记require_grad的变量)
optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.5)
# 在Windows编译需要将使用loader的地方封装在函数内,否则会报错。Ubuntu没有这个问题。
# 记住把epoch循环放在main函数内即可
if __name__ == '__main__':
#【train】
for epoch in range(1):
running_loss = 0.0
# 0表示从train_loader的指定索引0开始
for i, data in enumerate(train_loader, 0):
# 1. 准备数据
inputs, labels = data
# 2. 前向传播
y_pred = model(inputs)
# 构造好loss层后,就会自动生成计算图,可以自动求导
loss = criterion(y_pred, labels)
# 3. 反向传播
# 在反向传播之前,需要先梯度归零
optimizer.zero_grad()
loss.backward()
# 4. 更新
optimizer.step()
# 每300个batch输出一次loss
running_loss += loss.item()
if i % 300 == 299:
print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 300))
running_loss = 0.0
# 【test】
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
inputs, labels = data
y_pred = model(inputs)
# 沿着第1个维度(行是第0,列是第1)找最大值
_, predicted = torch.max(y_pred, dim=1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy on test set: %d %%' % (100 * correct / total))
卷积层和池化层使用方法:
import torch
in_channels, out_channels = 5, 10
width, height = 100, 100
kernel_size = 3
batch_size = 1
input = torch.randn(batch_size, in_channels, width, height)
conv_layer = torch.nn.Conv2d(in_channels, out_channels, padding=1, stride=2, kernel_size=kernel_size, bias=False)
output = conv_layer(input)
print(input.size())
print(output.size())
print(conv_layer.weight.size())
maxpooling_layer = torch.nn.MaxPool2d(kernel_size=2)
output = maxpooling_layer(input)
print(input.size())
print(output.size())
定义CNN示例:
# 定义模型
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
self.pooling = torch.nn.MaxPool2d(2)
self.fc = torch.nn.Linear(320, 10)
self.activate = torch.nn.ReLU()
def forward(self, x):
# x.size()表示batch_size*C*H*W格式,x.size(0)表示batch_size
batch_size = x.size(0)
x = self.conv1(x)
x = self.pooling(x) # ReLU和pooling先后顺序都行
x = self.activate(x)
x = self.conv2(x)
x = self.pooling(x)
x = self.activate(x)
x = x.view(batch_size, -1) # 把2维数据展平
x = self.fc(x)
return x
用cuda的方法:
# 1. 把模型放入gpu
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)
#2. 把数据放入gpu
for epoch in range(20):
for i, data in enumerate(train_loader, 0):
inputs, labels = data
inputs, labels = inputs.to(device), labels.to(device)