代码:
c = np.ones((3,3))
d = torch.from_numpy(c)
d.size()
d
源码:
X = np.linspace(start=0, stop=100, num=10000)
y = 3*X + 4 + np.random.uniform(0, 1, size=(10000,))
X = torch.from_numpy(X)
X = X.to(torch.float32)
y = torch.from_numpy(y)
y = y.to(torch.float32)
w = Variable(torch.randn(1), requires_grad=True)
b = Variable(torch.randn(1), requires_grad=True)
prediction = w*X + b
plt.scatter(X.data.numpy(), y.data.numpy())
plt.plot(X.data.numpy(), prediction.data.numpy(), 'r-', lw=2)
plt.show()
for epoch in range(500):
for i, (trn_x, trn_y) in enumerate(zip(X, y)):
z = w * trn_x + b
loss = torch.nn.functional.mse_loss(z, trn_y)
loss.backward()
w.data -= 1e-5*w.grad.data
b.data -= 1e-5*b.grad.data
l1 = w.grad.data.zero_()
l2 = b.grad.data.zero_()
if (epoch+1)%50 == 0:
print(loss)
prediction = w*X + b
plt.scatter(X.data.numpy(), y.data.numpy())
plt.plot(X.data.numpy(), prediction.data.numpy(), 'r-', lw=2)
plt.show()
class MyLinear(nn.Module):
def __init__(self, input_features, output):
super(Model, self).__init__()
self.w = Parameter(torch.randn(output, input_features, requires_grad=True))
self.b = Parameter(torch.randn(output, input_features, requires_grad=True))
# 给模型添加parameter
self.register_parameter('weight', self.w)
self.register_parameter('bias', self.b)
def forward(self, x):
return self.w*x + self.b
ps.注意self.register_parameter
,这个函数是给model.parameters()
添加元素(model.parameters()
是从一个字典逐步返回参数值),如果不添加,那么使用不了Pytorch
自带的优化器。
Pytorch
的nn.Linear
的使用(这里简单搭建一个只含全连接层的网络):
class Net(nn.Module):
def __init__(self, input_features, output):
super(Net, self).__init__()
self.fc1 = nn.Linear(input_features, 4)
self.fc2 = nn.Linear(4, output)
def forward(self, x):
out = self.fc1(x)
out = self.fc2(out)
return out
model = Net(5, 3)
print(model)
实现源码:
def elu(x, alpha=1.0, inplace=False):
# ELU(x)=max(0,x) + min(0,α∗(exp(x)−1))
zeros = torch.zeros_like(x)
left = torch.cat([x, zeros], dim=0)
right = alpha * (torch.exp(x) - 1)
right = torch.cat([zeros, right])
result = torch.max(left, dim=0)[0] + torch.min(right, dim=0)[0]
return result
def leaky_relu(x, negative_slope=0.01,inplace=False):
# LeakyReLU(x) = max(0,x) + negative_slope∗min(0,x)
zeros = torch.zeros_like(x)
cat_mat = torch.cat([x, zeros], dim=0)
result = torch.max(cat_mat, dim=0)[0] + negative_slope*torch.min(cat_mat, dim=0)[0]
return result
def p_relu(x, num_parameters=1, init=0.25):
# PReLU(x)=max(0,x)+a∗min(0,x)
zeros = torch.zeros_like(x)
cat_mat = torch.cat([x, zeros], dim=0)
result = torch.max(cat_mat, dim=0)[0] + init*torch.min(cat_mat, dim=0)[0]
return result
def relu(x, inplace=False):
# ReLU(x)=max(0,x)
zeros = torch.zeros_like(x)
cat_mat = torch.cat([x, zeros], dim=0)
result = torch.max(cat_mat, dim=0)[0]
return result
def relu6(x, inplace=False):
# ReLU6(x)=min(max(0,x),6)
mat_zero = torch.zeros_like(x)
x = torch.cat([x, mat_zero], dim=0)
result = torch.max(x, dim=0)[0]
result = torch.cat([torch.unsqueeze(result, dim=0), mat_zero+6], dim=0)
result = torch.min(result, dim=0)[0]
return result
def selu(x, inplace=True):
# SELU(x) = scale∗(max(0, x) + min(0, α∗(exp(x)−1)))
alpha = 1.6732632423543772848170429916717
scale = 1.0507009873554804934193349852946
zeros = torch.zeros_like(x)
left = torch.cat([x, zeros], dim=0)
right = alpha * (torch.exp(x) - 1)
right = torch.cat([zeros, right])
result = torch.max(left, dim=0)[0] + torch.min(right, dim=0)[0]
result *= scale
return result
def celu(x, alpha=1.0,inplace=False):
if not alpha:
raise Exception(f"{alpha}不能为0")
# CELU(x)=max(0,x)+min(0,α∗(exp(x/α)−1))
zeros = torch.zeros_like(x)
left = torch.cat([x, zeros], dim=0)
right = alpha * (torch.exp(x / alpha) - 1)
right = torch.cat([zeros, right])
result = torch.max(left, dim=0)[0] + torch.min(right, dim=0)[0]
return result
def sigmoid(x):
# Sigmoid(x) = 1 / (1 + exp(-x))
return 1 / (1 + torch.exp(-1 * x))
def log_sigmoid(x):
# LogSigmoid(x) = log(1 / (1 + exp(-x)))
return torch.log(sigmoid(x))
def tanh(x):
# Tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))
# solution 1:
# return torch.tanh(x)
# solution 2:
return (torch.exp(x) - torch.exp(-x)) / (torch.exp(x) + torch.exp(-x))
def tanh_shrink(x):
return x - tanh(x)
def soft_plus(x, beta=1,threshold=20):
#
if not beta:
raise
return 1/beta*torch.log(1+torch.exp(beta*x))
def soft_shrink(x: Tensor, lambd=0.5):
x.apply_(lambda x_: x_-lambd if x_ > lambd else x_+lambd if x_ < -lambd else 0)
return x
步骤1:理解卷积层的原理和具体使用
步骤2:计算下如下卷积层的参数量:
nn.Conv2d(
in_channels=1,
out_channels=32,
kernel_size=5,
stride=1,
padding=2
)
卷积层参数量计算方法:
总结一点就是:参数量=(filter size * 前一层特征图的通道数 )* 当前层filter数量+偏置数量
所以答案为: 5 × 5 × 1 × 32 + 32 = 832 5\times5\times1\times32+32=832 5×5×1×32+32=832
也可以使用相关库来查看:https://blog.csdn.net/qq_41979513/article/details/102369396
实现两种2d pool
,有两种方法:
max_pool = nn.MaxPool2d(kernel_size=3, stride=1, padding=0)
mean_pool = nn.AvgPool2d(kernel_size=3, stride=1, padding=0)
image = torch.randn(1, 3, 28, 28)
image.size()
max_pool(image).size()
mean_pool(image).size()
import torch.nn.functional as F
image = torch.randn(1, 3, 28, 28)
F.max_pool2d(image, kernel_size=3, stride=1, padding=0).size()
F.avg_pool2d(image, kernel_size=3, stride=1, padding=0).size()
学习链接:https://zhuanlan.zhihu.com/p/263527295
论文地址(推荐第一个地址):
论文中各种VGG结构如下图:
Table 1: ConvNet configurations (shown in columns). The depth of the configurations increases from the left (A) to the right (E), as more layers are added (the added layers are shown in bold). The convolutional layer parameters are denoted as “conv〈receptive field size〉-〈number of channels〉
”. The ReLU
activation function is not shown for brevity.
从上图可以看出,除A-LRN
、C
两列外,其余列的每行的卷积层都是一样的,所以我会分开两部分来复现,接下来看看一些细节,例如stride
和padding
。
开始复现:
import torch.nn as nn
import torch.nn.functional as F
from typing import List
# 第一部分
class VGG(nn.Module):
def __init__(self, arch: List[int], num_classes=1000):
super(VGG, self).__init__()
self.in_channels = 3
self.conv_pool1 = self.make_layer(64, arch[0])
self.conv_pool2 = self.make_layer(128, arch[1])
self.conv_pool3 = self.make_layer(256, arch[2])
self.conv_pool4 = self.make_layer(512, arch[3])
self.conv_pool5 = self.make_layer(512, arch[4])
self.fc1 = nn.Linear(7*7*512, 4096)
self.fc2 = nn.Linear(4096, 4096)
self.fc3 = nn.Linear(4096, num_classes)
def make_layer(self, output_channels, num):
layers = []
for _ in range(num):
layers.append(nn.Conv2d(self.in_channels, output_channels,
kernel_size=3, stride=1, padding=1))
layers.append(nn.ReLU())
self.in_channels = output_channels
layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
return nn.Sequential(*layers)
def forward(self, x):
out = self.conv_pool1(x)
out = self.conv_pool2(out)
out = self.conv_pool3(out)
out = self.conv_pool4(out)
out = self.conv_pool5(out)
out = out.view(out.size(0), -1)
out = self.fc1(out)
out = F.relu(out)
out = self.fc2(out)
out = F.relu(out)
out = self.fc3(out)
return F.softmax(out)
def VGG_11():
return VGG([1, 1, 2, 2, 2], num_classes=1000)
def VGG_13():
return VGG([1, 1, 2, 2, 2], num_classes=1000)
def VGG_16():
return VGG([2, 2, 3, 3, 3], num_classes=1000)
def VGG_19():
return VGG([2, 2, 4, 4, 4], num_classes=1000)
学习链接:https://zhuanlan.zhihu.com/p/263526658
学习链接:https://github.com/masoudrostami/Fashion-MNIST-using-PyTorch/blob/main/MNIST%20Fashion%20Project.ipynb
数据集下载
示例
# 导入相关库
import os, sys, codecs, glob
from PIL import Image, ImageDraw
import numpy as np
import pandas as pd
import cv2
import torch
torch.backends.cudnn.benchmark = False
import torchvision.models as models
import torchvision.transforms as transforms
import torchvision.datasets as datasets
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from torch.utils.data.dataset import Dataset
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all'
import time
import random
接下来定义和创建Dataset类数据集
# 定义
class MyDataset(Dataset):
def __init__(self, img, keypoint, transform=None):
self.img = img
self.transform = transform
self.keypoint = keypoint
def __getitem__(self, index):
img = Image.fromarray(self.img[:, :, index]).convert('RGB')
if self.transform is not None:
img = self.transform(img)
return img, self.keypoint[index] / 96.0 # 除以96是为了归一化
def __len__(self):
return self.img.shape[-1]
接着导入相关数据:
其中test.npy
暂时用不到,要有fillna
,因为标签有空值。
imgs_trans = transforms.Compose([transforms.ToTensor(),])
train_dataset = MyDataset(train_img[:, :, :-500], train_df.values[:-500], imgs_trans)
train_loader = torch.utils.data.DataLoader(
train_dataset, batch_size=10, shuffle=True, num_workers=5
)
val_dataset = MyDataset(train_img[:, :, -500:], train_df.values[-500:], imgs_trans)
val_loader = torch.utils.data.DataLoader(
val_dataset, batch_size=10, shuffle=False, num_workers=5
)
定义自己的模型,四层卷积核两层全连接:
class Model(nn.Module):
def __init__(self):
self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3) #94
self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3) #92
self.conv3 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3) #90
self.conv4 = nn.Conv2d(in_channels=128, out_channels=64, kernel_size=3) # 88
self.fc1 = nn.Linear(64*88*88, 128)
self.fc2 = nn.Linear(128, 8)
super(Model, self).__init__()
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = self.conv3(x)
x = F.relu(x)
x = self.conv4(x)
x = F.relu(x)
x = x.view(x.size(0), -1)
x = self.fc1(x)
x = F.relu(x)
x = self.fc2(x)
x = F.relu(x)
return feat
from tqdm import tqdm
from sklearn.metrics import mean_absolute_error
def train(train_dat, model, criterion, optimizer, epoch):
model.train()
for i, (input, target) in enumerate(tqdm(train_dat)):
input = Variable(input).float().cuda()
target = Variable(target).float().cuda()
output = model(input, target)
loss = criterion(output, target)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f"train dataset's loss: {loss.data}")
def evaluate(val_dat, net):
net.eval()
val_preds = []
with torch.no_grad():
end = time.time()
for i, (input, target) in enumerate(tqdm(val_dat)):
input = input.float().cuda()
target = target.float().cuda()
output = net(input)
val_preds.append(output.data)
val_loss = mean_absolute_error(torch.cat(val_preds)*96, train_df.values[-500:])
print(f"valid dataset's loss: {val_loss}")
model = XunFeiNet().cuda()
criterion = nn.MSELoss().cuda()
optimizer = torch.optim.Adam(model.parameters(), 0.001)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.85)
for epoch in range(1):
print('Epoch: ', epoch)
train(train_loader, model, criterion, optimizer, epoch)
evaluate(val_loader, model)
scheduler.step()