Repository: TingsongYu/PyTorch_Tutorial
Branch: master
Commit: 38fae4a41144
Files: 33
Total size: 53.1 KB
Directory structure:
gitextract_lx1nh74y/
├── .gitignore
├── Code/
│ ├── 1_data_prepare/
│ │ ├── 1_1_cifar10_to_png.py
│ │ ├── 1_2_split_dataset.py
│ │ ├── 1_3_generate_txt.py
│ │ ├── 1_3_mydataset.py
│ │ └── 1_5_compute_mean.py
│ ├── 2_model/
│ │ ├── 2_finetune.py
│ │ └── net_params.pkl
│ ├── 3_optimizer/
│ │ ├── 3_1_lossFunction/
│ │ │ ├── 1_L1Loss.py
│ │ │ ├── 2_MSELoss.py
│ │ │ ├── 3_CrossEntropyLoss.py
│ │ │ ├── 4_NLLLoss.py
│ │ │ ├── 5_PoissonNLLLoss.py
│ │ │ └── 6_KLDivLoss.py
│ │ └── 3_2_optimizer/
│ │ ├── 1_param_groups.py
│ │ ├── 2_zero_grad.py
│ │ ├── 3_state_dict.py
│ │ ├── 4_load_state_dict.py
│ │ ├── 5_add_param_group.py
│ │ └── net_params.pkl
│ ├── 4_viewer/
│ │ ├── 1_tensorboardX_demo.py
│ │ ├── 2_visual_weights.py
│ │ ├── 3_visual_featuremaps.py
│ │ ├── 4_hist_grad_weight.py
│ │ ├── 5_Show_ConfMat.py
│ │ └── 6_hook_for_grad_cam.py
│ ├── main_training/
│ │ └── main.py
│ └── utils/
│ ├── __init__.py
│ └── utils.py
├── Data/
│ ├── net_params_72p.pkl
│ └── visual.txt
├── readme.md
└── requirements.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.py[cod]
*.so
*.egg
*.egg-info
*.DS_Store
================================================
FILE: Code/1_data_prepare/1_1_cifar10_to_png.py
================================================
# coding:utf-8
"""
将cifar10的data_batch_12345 转换成 png格式的图片
每个类别单独存放在一个文件夹,文件夹名称为0-9
"""
from imageio import imwrite
import numpy as np
import os
import pickle
base_dir = "D:/python 11/新建文件夹/practise/pytorch" #修改为当前Data 目录所在的绝对路径
data_dir = os.path.join(base_dir, "Data", "cifar-10-batches-py")
train_o_dir = os.path.join( base_dir, "Data", "cifar-10-png", "raw_train")
test_o_dir = os.path.join( base_dir, "Data", "cifar-10-png", "raw_test")
Train = False # 不解压训练集,仅解压测试集
# 解压缩,返回解压后的字典
def unpickle(file):
with open(file, 'rb') as fo:
dict_ = pickle.load(fo, encoding='bytes')
return dict_
def my_mkdir(my_dir):
if not os.path.isdir(my_dir):
os.makedirs(my_dir)
# 生成训练集图片,
if __name__ == '__main__':
if Train:
for j in range(1, 6):
data_path = os.path.join(data_dir, "data_batch_" + str(j)) # data_batch_12345
train_data = unpickle(data_path)
print(data_path + " is loading...")
for i in range(0, 10000):
img = np.reshape(train_data[b'data'][i], (3, 32, 32))
img = img.transpose(1, 2, 0)
label_num = str(train_data[b'labels'][i])
o_dir = os.path.join(train_o_dir, label_num)
my_mkdir(o_dir)
img_name = label_num + '_' + str(i + (j - 1)*10000) + '.png'
img_path = os.path.join(o_dir, img_name)
imwrite(img_path, img)
print(data_path + " loaded.")
print("test_batch is loading...")
# 生成测试集图片
test_data_path = os.path.join(data_dir, "test_batch")
test_data = unpickle(test_data_path)
for i in range(0, 10000):
img = np.reshape(test_data[b'data'][i], (3, 32, 32))
img = img.transpose(1, 2, 0)
label_num = str(test_data[b'labels'][i])
o_dir = os.path.join(test_o_dir, label_num)
my_mkdir(o_dir)
img_name = label_num + '_' + str(i) + '.png'
img_path = os.path.join(o_dir, img_name)
imwrite(img_path, img)
print("test_batch loaded.")
================================================
FILE: Code/1_data_prepare/1_2_split_dataset.py
================================================
# coding: utf-8
"""
将原始数据集进行划分成训练集、验证集和测试集
"""
import os
import glob
import random
import shutil
dataset_dir = os.path.join("..", "..", "Data", "cifar-10-png", "raw_test")
train_dir = os.path.join("..", "..", "Data", "train")
valid_dir = os.path.join("..", "..", "Data", "valid")
test_dir = os.path.join("..", "..", "Data", "test")
train_per = 0.8
valid_per = 0.1
test_per = 0.1
def makedir(new_dir):
if not os.path.exists(new_dir):
os.makedirs(new_dir)
if __name__ == '__main__':
for root, dirs, files in os.walk(dataset_dir):
for sDir in dirs:
imgs_list = glob.glob(os.path.join(root, sDir, '*.png'))
random.seed(666)
random.shuffle(imgs_list)
imgs_num = len(imgs_list)
train_point = int(imgs_num * train_per)
valid_point = int(imgs_num * (train_per + valid_per))
for i in range(imgs_num):
if i < train_point:
out_dir = os.path.join(train_dir, sDir)
elif i < valid_point:
out_dir = os.path.join(valid_dir, sDir)
else:
out_dir = os.path.join(test_dir, sDir)
makedir(out_dir)
out_path = os.path.join(out_dir, os.path.split(imgs_list[i])[-1])
shutil.copy(imgs_list[i], out_path)
print('Class:{}, train:{}, valid:{}, test:{}'.format(sDir, train_point, valid_point-train_point, imgs_num-valid_point))
================================================
FILE: Code/1_data_prepare/1_3_generate_txt.py
================================================
# coding:utf-8
import os
'''
为数据集生成对应的txt文件
'''
train_txt_path = os.path.join("..", "..", "Data", "train.txt")
train_dir = os.path.join("..", "..", "Data", "train")
valid_txt_path = os.path.join("..", "..", "Data", "valid.txt")
valid_dir = os.path.join("..", "..", "Data", "valid")
def gen_txt(txt_path, img_dir):
f = open(txt_path, 'w')
for root, s_dirs, _ in os.walk(img_dir, topdown=True): # 获取 train文件下各文件夹名称
for sub_dir in s_dirs:
i_dir = os.path.join(root, sub_dir) # 获取各类的文件夹 绝对路径
img_list = os.listdir(i_dir) # 获取类别文件夹下所有png图片的路径
for i in range(len(img_list)):
if not img_list[i].endswith('png'): # 若不是png文件,跳过
continue
label = img_list[i].split('_')[0]
img_path = os.path.join(i_dir, img_list[i])
line = img_path + ' ' + label + '\n'
f.write(line)
f.close()
if __name__ == '__main__':
gen_txt(train_txt_path, train_dir)
gen_txt(valid_txt_path, valid_dir)
================================================
FILE: Code/1_data_prepare/1_3_mydataset.py
================================================
# coding: utf-8
from PIL import Image
from torch.utils.data import Dataset
class MyDataset(Dataset):
def __init__(self, txt_path, transform=None, target_transform=None):
fh = open(txt_path, 'r')
imgs = []
for line in fh:
line = line.rstrip()
words = line.split()
imgs.append((words[0], int(words[1])))
self.imgs = imgs # 最主要就是要生成这个list, 然后DataLoader中给index,通过getitem读取图片数据
self.transform = transform
self.target_transform = target_transform
def __getitem__(self, index):
fn, label = self.imgs[index]
img = Image.open(fn).convert('RGB') # 像素值 0~255,在transfrom.totensor会除以255,使像素值变成 0~1
if self.transform is not None:
img = self.transform(img) # 在这里做transform,转为tensor等等
return img, label
def __len__(self):
return len(self.imgs)
================================================
FILE: Code/1_data_prepare/1_5_compute_mean.py
================================================
# coding: utf-8
import numpy as np
import cv2
import random
import os
"""
随机挑选CNum张图片,进行按通道计算均值mean和标准差std
先将像素从0~255归一化至 0-1 再计算
"""
train_txt_path = os.path.join("..", "..", "Data/train.txt")
CNum = 2000 # 挑选多少图片进行计算
img_h, img_w = 32, 32
imgs = np.zeros([img_w, img_h, 3, 1])
means, stdevs = [], []
with open(train_txt_path, 'r') as f:
lines = f.readlines()
random.shuffle(lines) # shuffle , 随机挑选图片
for i in range(CNum):
img_path = lines[i].rstrip().split()[0]
img = cv2.imread(img_path)
img = cv2.resize(img, (img_h, img_w))
img = img[:, :, :, np.newaxis]
imgs = np.concatenate((imgs, img), axis=3)
print(i)
imgs = imgs.astype(np.float32)/255.
for i in range(3):
pixels = imgs[:,:,i,:].ravel() # 拉成一行
means.append(np.mean(pixels))
stdevs.append(np.std(pixels))
means.reverse() # BGR --> RGB
stdevs.reverse()
print("normMean = {}".format(means))
print("normStd = {}".format(stdevs))
print('transforms.Normalize(normMean = {}, normStd = {})'.format(means, stdevs))
================================================
FILE: Code/2_model/2_finetune.py
================================================
# coding: utf-8
import torch
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
import numpy as np
import os
from torch.autograd import Variable
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import sys
sys.path.append("..")
from utils.utils import MyDataset, validate, show_confMat
from datetime import datetime
train_txt_path = os.path.join("..", "..", "Data", "train.txt")
valid_txt_path = os.path.join("..", "..", "Data", "valid.txt")
classes_name = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
train_bs = 16
valid_bs = 16
lr_init = 0.001
max_epoch = 1
# log
result_dir = os.path.join("..", "..", "Result")
now_time = datetime.now()
time_str = datetime.strftime(now_time, '%m-%d_%H-%M-%S')
log_dir = os.path.join(result_dir, time_str)
if not os.path.exists(log_dir):
os.makedirs(log_dir)
# -------------------------------------------- step 1/5 : 加载数据 -------------------------------------------
# 数据预处理设置
normMean = [0.4948052, 0.48568845, 0.44682974]
normStd = [0.24580306, 0.24236229, 0.2603115]
normTransform = transforms.Normalize(normMean, normStd)
trainTransform = transforms.Compose([
transforms.Resize(32),
transforms.RandomCrop(32, padding=4),
transforms.ToTensor(),
normTransform
])
validTransform = transforms.Compose([
transforms.ToTensor(),
normTransform
])
# 构建MyDataset实例
train_data = MyDataset(txt_path=train_txt_path, transform=trainTransform)
valid_data = MyDataset(txt_path=valid_txt_path, transform=validTransform)
# 构建DataLoder
train_loader = DataLoader(dataset=train_data, batch_size=train_bs, shuffle=True)
valid_loader = DataLoader(dataset=valid_data, batch_size=valid_bs)
# ------------------------------------ step 2/5 : 定义网络 ------------------------------------
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.pool2 = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool1(F.relu(self.conv1(x)))
x = self.pool2(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
# 定义权值初始化
def initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
torch.nn.init.xavier_normal_(m.weight.data)
if m.bias is not None:
m.bias.data.zero_()
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
elif isinstance(m, nn.Linear):
torch.nn.init.normal_(m.weight.data, 0, 0.01)
m.bias.data.zero_()
net = Net() # 创建一个网络
# ================================ #
# finetune 权值初始化
# ================================ #
# load params
pretrained_dict = torch.load('net_params.pkl')
# 获取当前网络的dict
net_state_dict = net.state_dict()
# 剔除不匹配的权值参数
pretrained_dict_1 = {k: v for k, v in pretrained_dict.items() if k in net_state_dict}
# 更新新模型参数字典
net_state_dict.update(pretrained_dict_1)
# 将包含预训练模型参数的字典"放"到新模型中
net.load_state_dict(net_state_dict)
# ------------------------------------ step 3/5 : 定义损失函数和优化器 ------------------------------------
# ================================= #
# 按需设置学习率
# ================================= #
# 将fc3层的参数从原始网络参数中剔除
ignored_params = list(map(id, net.fc3.parameters()))
base_params = filter(lambda p: id(p) not in ignored_params, net.parameters())
# 为fc3层设置需要的学习率
optimizer = optim.SGD([
{'params': base_params},
{'params': net.fc3.parameters(), 'lr': lr_init*10}], lr_init, momentum=0.9, weight_decay=1e-4)
criterion = nn.CrossEntropyLoss() # 选择损失函数
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=50, gamma=0.1) # 设置学习率下降策略
# ------------------------------------ step 4/5 : 训练 --------------------------------------------------
for epoch in range(max_epoch):
loss_sigma = 0.0 # 记录一个epoch的loss之和
correct = 0.0
total = 0.0
scheduler.step() # 更新学习率
for i, data in enumerate(train_loader):
# 获取图片和标签
inputs, labels = data
inputs, labels = Variable(inputs), Variable(labels)
# forward, backward, update weights
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# 统计预测信息
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).squeeze().sum().numpy()
loss_sigma += loss.item()
# 每10个iteration 打印一次训练信息,loss为10个iteration的平均
if i % 10 == 9:
loss_avg = loss_sigma / 10
loss_sigma = 0.0
print("Training: Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(
epoch + 1, max_epoch, i + 1, len(train_loader), loss_avg, correct / total))
print('参数组1的学习率:{}, 参数组2的学习率:{}'.format(scheduler.get_lr()[0], scheduler.get_lr()[1]))
# ------------------------------------ 观察模型在验证集上的表现 ------------------------------------
loss_sigma = 0.0
cls_num = len(classes_name)
conf_mat = np.zeros([cls_num, cls_num]) # 混淆矩阵
net.eval()
for i, data in enumerate(valid_loader):
# 获取图片和标签
images, labels = data
images, labels = Variable(images), Variable(labels)
# forward
outputs = net(images)
outputs.detach_()
# 计算loss
loss = criterion(outputs, labels)
loss_sigma += loss.item()
# 统计
_, predicted = torch.max(outputs.data, 1)
# labels = labels.data # Variable --> tensor
# 统计混淆矩阵
for j in range(len(labels)):
cate_i = labels[j].numpy()
pre_i = predicted[j].numpy()
conf_mat[cate_i, pre_i] += 1.0
print('{} set Accuracy:{:.2%}'.format('Valid', conf_mat.trace() / conf_mat.sum()))
print('Finished Training')
# ------------------------------------ step5: 绘制混淆矩阵图 ------------------------------------
conf_mat_train, train_acc = validate(net, train_loader, 'train', classes_name)
conf_mat_valid, valid_acc = validate(net, valid_loader, 'valid', classes_name)
show_confMat(conf_mat_train, classes_name, 'train', log_dir)
show_confMat(conf_mat_valid, classes_name, 'valid', log_dir)
================================================
FILE: Code/3_optimizer/3_1_lossFunction/1_L1Loss.py
================================================
# coding: utf-8
import torch
import torch.nn as nn
# ----------------------------------- L1 Loss
# 生成网络输出 以及 目标输出
output = torch.ones(2, 2, requires_grad=True)*0.5
target = torch.ones(2, 2)
# 设置三种不同参数的L1Loss
reduce_False = nn.L1Loss(size_average=True, reduce=False)
size_average_True = nn.L1Loss(size_average=True, reduce=True)
size_average_False = nn.L1Loss(size_average=False, reduce=True)
o_0 = reduce_False(output, target)
o_1 = size_average_True(output, target)
o_2 = size_average_False(output, target)
print('\nreduce=False, 输出同维度的loss:\n{}\n'.format(o_0))
print('size_average=True,\t求平均:\t{}'.format(o_1))
print('size_average=False,\t求和:\t{}'.format(o_2))
================================================
FILE: Code/3_optimizer/3_1_lossFunction/2_MSELoss.py
================================================
# coding: utf-8
import torch
import torch.nn as nn
# ----------------------------------- MSE loss
# 生成网络输出 以及 目标输出
output = torch.ones(2, 2, requires_grad=True) * 0.5
target = torch.ones(2, 2)
# 设置三种不同参数的L1Loss
reduce_False = nn.MSELoss(size_average=True, reduce=False)
size_average_True = nn.MSELoss(size_average=True, reduce=True)
size_average_False = nn.MSELoss(size_average=False, reduce=True)
o_0 = reduce_False(output, target)
o_1 = size_average_True(output, target)
o_2 = size_average_False(output, target)
print('\nreduce=False, 输出同维度的loss:\n{}\n'.format(o_0))
print('size_average=True,\t求平均:\t{}'.format(o_1))
print('size_average=False,\t求和:\t{}'.format(o_2))
================================================
FILE: Code/3_optimizer/3_1_lossFunction/3_CrossEntropyLoss.py
================================================
# coding: utf-8
import torch
import torch.nn as nn
import numpy as np
import math
# ----------------------------------- CrossEntropy loss: base
loss_f = nn.CrossEntropyLoss(weight=None, size_average=True, reduce=False)
# 生成网络输出 以及 目标输出
output = torch.ones(2, 3, requires_grad=True) * 0.5 # 假设一个三分类任务,batchsize=2,假设每个神经元输出都为0.5
target = torch.from_numpy(np.array([0, 1])).type(torch.LongTensor)
loss = loss_f(output, target)
print('--------------------------------------------------- CrossEntropy loss: base')
print('loss: ', loss)
print('由于reduce=False,所以可以看到每一个样本的loss,输出为[1.0986, 1.0986]')
# 熟悉计算公式,手动计算第一个样本
output = output[0].detach().numpy()
output_1 = output[0] # 第一个样本的输出值
target_1 = target[0].numpy()
# 第一项
x_class = output[target_1]
# 第二项
exp = math.e
sigma_exp_x = pow(exp, output[0]) + pow(exp, output[1]) + pow(exp, output[2])
log_sigma_exp_x = math.log(sigma_exp_x)
# 两项相加
loss_1 = -x_class + log_sigma_exp_x
print('--------------------------------------------------- 手动计算')
print('第一个样本的loss:', loss_1)
# ----------------------------------- CrossEntropy loss: weight
weight = torch.from_numpy(np.array([0.6, 0.2, 0.2])).float()
loss_f = nn.CrossEntropyLoss(weight=weight, size_average=True, reduce=False)
output = torch.ones(2, 3, requires_grad=True) * 0.5 # 假设一个三分类任务,batchsize为2个,假设每个神经元输出都为0.5
target = torch.from_numpy(np.array([0, 1])).type(torch.LongTensor)
loss = loss_f(output, target)
print('\n\n--------------------------------------------------- CrossEntropy loss: weight')
print('loss: ', loss) #
print('原始loss值为1.0986, 第一个样本是第0类,weight=0.6,所以输出为1.0986*0.6 =', 1.0986*0.6)
# ----------------------------------- CrossEntropy loss: ignore_index
loss_f_1 = nn.CrossEntropyLoss(weight=None, size_average=False, reduce=False, ignore_index=1)
loss_f_2 = nn.CrossEntropyLoss(weight=None, size_average=False, reduce=False, ignore_index=2)
output = torch.ones(3, 3, requires_grad=True) * 0.5 # 假设一个三分类任务,batchsize为2个,假设每个神经元输出都为0.5
target = torch.from_numpy(np.array([0, 1, 2])).type(torch.LongTensor)
loss_1 = loss_f_1(output, target)
loss_2 = loss_f_2(output, target)
print('\n\n--------------------------------------------------- CrossEntropy loss: ignore_index')
print('ignore_index = 1: ', loss_1) # 类别为1的样本的loss为0
print('ignore_index = 2: ', loss_2) # 类别为2的样本的loss为0
================================================
FILE: Code/3_optimizer/3_1_lossFunction/4_NLLLoss.py
================================================
# coding: utf-8
import torch
import torch.nn as nn
import numpy as np
# ----------------------------------- log likelihood loss
# 各类别权重
weight = torch.from_numpy(np.array([0.6, 0.2, 0.2])).float()
# 生成网络输出 以及 目标输出
output = torch.from_numpy(np.array([[0.7, 0.2, 0.1], [0.4, 1.2, 0.4]])).float()
output.requires_grad = True
target = torch.from_numpy(np.array([0, 0])).type(torch.LongTensor)
loss_f = nn.NLLLoss(weight=weight, size_average=True, reduce=False)
loss = loss_f(output, target)
print('\nloss: \n', loss)
print('\n第一个样本是0类,loss = -(0.6*0.7)={}'.format(loss[0]))
print('\n第二个样本是0类,loss = -(0.6*0.4)={}'.format(loss[1]))
================================================
FILE: Code/3_optimizer/3_1_lossFunction/5_PoissonNLLLoss.py
================================================
# coding: utf-8
import torch
import torch.nn as nn
import numpy as np
# ----------------------------------- Poisson NLLLoss
# 生成网络输出 以及 目标输出
log_input = torch.randn(5, 2, requires_grad=True)
target = torch.randn(5, 2)
loss_f = nn.PoissonNLLLoss()
loss = loss_f(log_input, target)
print('\nloss: \n', loss)
================================================
FILE: Code/3_optimizer/3_1_lossFunction/6_KLDivLoss.py
================================================
# coding: utf-8
import torch
import torch.nn as nn
import numpy as np
# ----------------------------------- KLDiv loss
loss_f = nn.KLDivLoss(size_average=False, reduce=False)
loss_f_mean = nn.KLDivLoss(size_average=True, reduce=True)
# 生成网络输出 以及 目标输出
output = torch.from_numpy(np.array([[0.1132, 0.5477, 0.3390]])).float()
output.requires_grad = True
target = torch.from_numpy(np.array([[0.8541, 0.0511, 0.0947]])).float()
loss_1 = loss_f(output, target)
loss_mean = loss_f_mean(output, target)
print('\nloss: ', loss_1)
print('\nloss_mean: ', loss_mean)
# 熟悉计算公式,手动计算样本的第一个元素的loss,注意这里只有一个样本,是 element-wise计算的
output = output[0].detach().numpy()
output_1 = output[0] # 第一个样本的第一个元素
target_1 = target[0][0].numpy()
loss_1 = target_1 * (np.log(target_1) - output_1)
print('\n第一个样本第一个元素的loss:', loss_1)
================================================
FILE: Code/3_optimizer/3_2_optimizer/1_param_groups.py
================================================
# coding: utf-8
import torch
import torch.optim as optim
w1 = torch.randn(2, 2)
w1.requires_grad = True
w2 = torch.randn(2, 2)
w2.requires_grad = True
w3 = torch.randn(2, 2)
w3.requires_grad = True
# 一个参数组
optimizer_1 = optim.SGD([w1, w3], lr=0.1)
print('len(optimizer.param_groups): ', len(optimizer_1.param_groups))
print(optimizer_1.param_groups, '\n')
# 两个参数组
optimizer_2 = optim.SGD([{'params': w1, 'lr': 0.1},
{'params': w2, 'lr': 0.001}])
print('len(optimizer.param_groups): ', len(optimizer_2.param_groups))
print(optimizer_2.param_groups)
================================================
FILE: Code/3_optimizer/3_2_optimizer/2_zero_grad.py
================================================
# coding: utf-8
import torch
import torch.optim as optim
# ----------------------------------- zero_grad
w1 = torch.randn(2, 2)
w1.requires_grad = True
w2 = torch.randn(2, 2)
w2.requires_grad = True
optimizer = optim.SGD([w1, w2], lr=0.001, momentum=0.9)
optimizer.param_groups[0]['params'][0].grad = torch.randn(2, 2)
print('参数w1的梯度:')
print(optimizer.param_groups[0]['params'][0].grad, '\n') # 参数组,第一个参数(w1)的梯度
optimizer.zero_grad()
print('执行zero_grad()之后,参数w1的梯度:')
print(optimizer.param_groups[0]['params'][0].grad) # 参数组,第一个参数(w1)的梯度
================================================
FILE: Code/3_optimizer/3_2_optimizer/3_state_dict.py
================================================
# coding: utf-8
import torch.nn as nn
import torch.nn.functional as F
# ----------------------------------- state_dict
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 1, 3)
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(1 * 3 * 3, 2)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = x.view(-1, 1 * 3 * 3)
x = F.relu(self.fc1(x))
return x
net = Net()
# 获取网络当前参数
net_state_dict = net.state_dict()
print('net_state_dict类型:', type(net_state_dict))
print('net_state_dict管理的参数: ', net_state_dict.keys())
for key, value in net_state_dict.items():
print('参数名: ', key, '\t大小: ', value.shape)
================================================
FILE: Code/3_optimizer/3_2_optimizer/4_load_state_dict.py
================================================
# coding: utf-8
import torch
import torch.nn as nn
import torch.nn.functional as F
# ----------------------------------- load_state_dict
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 1, 3)
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(1 * 3 * 3, 2)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = x.view(-1, 1 * 3 * 3)
x = F.relu(self.fc1(x))
return x
def zero_param(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
torch.nn.init.constant_(m.weight.data, 0)
if m.bias is not None:
m.bias.data.zero_()
elif isinstance(m, nn.Linear):
torch.nn.init.constant_(m.weight.data, 0)
m.bias.data.zero_()
net = Net()
# 保存,并加载模型参数(仅保存模型参数)
torch.save(net.state_dict(), 'net_params.pkl') # 假设训练好了一个模型net
pretrained_dict = torch.load('net_params.pkl')
# 将net的参数全部置0,方便对比
net.zero_param()
net_state_dict = net.state_dict()
print('conv1层的权值为:\n', net_state_dict['conv1.weight'], '\n')
# 通过load_state_dict 加载参数
net.load_state_dict(pretrained_dict)
print('加载之后,conv1层的权值变为:\n', net_state_dict['conv1.weight'])
================================================
FILE: Code/3_optimizer/3_2_optimizer/5_add_param_group.py
================================================
# coding: utf-8
import torch
import torch.optim as optim
# ----------------------------------- add_param_group
w1 = torch.randn(2, 2)
w1.requires_grad = True
w2 = torch.randn(2, 2)
w2.requires_grad = True
w3 = torch.randn(2, 2)
w3.requires_grad = True
# 一个参数组
optimizer_1 = optim.SGD([w1, w2], lr=0.1)
print('当前参数组个数: ', len(optimizer_1.param_groups))
print(optimizer_1.param_groups, '\n')
# 增加一个参数组
print('增加一组参数 w3\n')
optimizer_1.add_param_group({'params': w3, 'lr': 0.001, 'momentum': 0.8})
print('当前参数组个数: ', len(optimizer_1.param_groups))
print(optimizer_1.param_groups, '\n')
print('可以看到,参数组是一个list,一个元素是一个dict,每个dict中都有lr, momentum等参数,这些都是可单独管理,单独设定,十分灵活!')
================================================
FILE: Code/4_viewer/1_tensorboardX_demo.py
================================================
# coding: utf-8
import os
import torch
import torchvision.utils as vutils
import numpy as np
import torchvision.models as models
from torchvision import datasets
from tensorboardX import SummaryWriter
resnet18 = models.resnet18(False)
writer = SummaryWriter(os.path.join("..", "..", "Result", "runs"))
sample_rate = 44100
freqs = [262, 294, 330, 349, 392, 440, 440, 440, 440, 440, 440]
true_positive_counts = [75, 64, 21, 5, 0]
false_positive_counts = [150, 105, 18, 0, 0]
true_negative_counts = [0, 45, 132, 150, 150]
false_negative_counts = [0, 11, 54, 70, 75]
precision = [0.3333333, 0.3786982, 0.5384616, 1.0, 0.0]
recall = [1.0, 0.8533334, 0.28, 0.0666667, 0.0]
for n_iter in range(100):
s1 = torch.rand(1) # value to keep
s2 = torch.rand(1)
# data grouping by `slash`
writer.add_scalar(os.path.join("data", "scalar_systemtime"), s1[0], n_iter)
# data grouping by `slash`
writer.add_scalar(os.path.join("data", "scalar_customtime"), s1[0], n_iter, walltime=n_iter)
writer.add_scalars(os.path.join("data", "scalar_group"), {"xsinx": n_iter * np.sin(n_iter),
"xcosx": n_iter * np.cos(n_iter),
"arctanx": np.arctan(n_iter)}, n_iter)
x = torch.rand(32, 3, 64, 64) # output from network
if n_iter % 10 == 0:
x = vutils.make_grid(x, normalize=True, scale_each=True)
writer.add_image('Image', x, n_iter) # Tensor
# writer.add_image('astronaut', skimage.data.astronaut(), n_iter) # numpy
# writer.add_image('imread',
# skimage.io.imread('screenshots/audio.png'), n_iter) # numpy
x = torch.zeros(sample_rate * 2)
for i in range(x.size(0)):
# sound amplitude should in [-1, 1]
x[i] = np.cos(freqs[n_iter // 10] * np.pi *
float(i) / float(sample_rate))
writer.add_audio('myAudio', x, n_iter)
writer.add_text('Text', 'text logged at step:' + str(n_iter), n_iter)
writer.add_text('markdown Text', '''a|b\n-|-\nc|d''', n_iter)
for name, param in resnet18.named_parameters():
if 'bn' not in name:
writer.add_histogram(name, param, n_iter)
writer.add_pr_curve('xoxo', np.random.randint(2, size=100), np.random.rand(
100), n_iter) # needs tensorboard 0.4RC or later
writer.add_pr_curve_raw('prcurve with raw data', true_positive_counts,
false_positive_counts,
true_negative_counts,
false_negative_counts,
precision,
recall, n_iter)
# export scalar data to JSON for external processing
writer.export_scalars_to_json(os.path.join("..", "..", "Result", "all_scalars.json"))
dataset = datasets.MNIST(os.path.join("..", "..", "Data", "mnist"), train=False, download=True)
images = dataset.test_data[:100].float()
label = dataset.test_labels[:100]
features = images.view(100, 784)
writer.add_embedding(features, metadata=label, label_img=images.unsqueeze(1))
writer.add_embedding(features, global_step=1, tag='noMetadata')
dataset = datasets.MNIST(os.path.join("..", "..", "Data", "mnist"), train=True, download=True)
images_train = dataset.train_data[:100].float()
labels_train = dataset.train_labels[:100]
features_train = images_train.view(100, 784)
all_features = torch.cat((features, features_train))
all_labels = torch.cat((label, labels_train))
all_images = torch.cat((images, images_train))
dataset_label = ['test'] * 100 + ['train'] * 100
all_labels = list(zip(all_labels, dataset_label))
writer.add_embedding(all_features, metadata=all_labels, label_img=all_images.unsqueeze(1),
metadata_header=['digit', 'dataset'], global_step=2)
# VIDEO
vid_images = dataset.train_data[:16 * 48]
vid = vid_images.view(16, 1, 48, 28, 28) # BxCxTxHxW
writer.add_video('video', vid_tensor=vid)
writer.add_video('video_1_fps', vid_tensor=vid, fps=1)
writer.close()
================================================
FILE: Code/4_viewer/2_visual_weights.py
================================================
# coding: utf-8
import os
import torch
import torchvision.utils as vutils
from tensorboardX import SummaryWriter
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.pool2 = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool1(F.relu(self.conv1(x)))
x = self.pool2(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
# 定义权值初始化
def initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
torch.nn.init.xavier_normal_(m.weight.data)
if m.bias is not None:
m.bias.data.zero_()
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
elif isinstance(m, nn.Linear):
torch.nn.init.normal_(m.weight.data, 0, 0.01)
m.bias.data.zero_()
net = Net() # 创建一个网络
pretrained_dict = torch.load(os.path.join("..", "2_model", "net_params.pkl"))
net.load_state_dict(pretrained_dict)
writer = SummaryWriter(log_dir=os.path.join("..", "..", "Result", "visual_weights"))
params = net.state_dict()
for k, v in params.items():
if 'conv' in k and 'weight' in k:
c_int = v.size()[1] # 输入层通道数
c_out = v.size()[0] # 输出层通道数
# 以feature map为单位,绘制一组卷积核,一张feature map对应的卷积核个数为输入通道数
for j in range(c_out):
print(k, v.size(), j)
kernel_j = v[j, :, :, :].unsqueeze(1) # 压缩维度,为make_grid制作输入
kernel_grid = vutils.make_grid(kernel_j, normalize=True, scale_each=True, nrow=c_int) # 1*输入通道数, w, h
writer.add_image(k+'_split_in_channel', kernel_grid, global_step=j) # j 表示feature map数
# 将一个卷积层的卷积核绘制在一起,每一行是一个feature map的卷积核
k_w, k_h = v.size()[-1], v.size()[-2]
kernel_all = v.view(-1, 1, k_w, k_h)
kernel_grid = vutils.make_grid(kernel_all, normalize=True, scale_each=True, nrow=c_int) # 1*输入通道数, w, h
writer.add_image(k + '_all', kernel_grid, global_step=666)
writer.close()
================================================
FILE: Code/4_viewer/3_visual_featuremaps.py
================================================
# coding: utf-8
import os
import torch
import torchvision.utils as vutils
import numpy as np
from tensorboardX import SummaryWriter
import torch.nn.functional as F
import torchvision.transforms as transforms
import sys
sys.path.append("..")
from utils.utils import MyDataset, Net, normalize_invert
from torch.utils.data import DataLoader
vis_layer = 'conv1'
log_dir = os.path.join("..", "..", "Result", "visual_featuremaps")
txt_path = os.path.join("..", "..", "Data", "visual.txt")
pretrained_path = os.path.join("..", "..", "Data", "net_params_72p.pkl")
net = Net()
pretrained_dict = torch.load(pretrained_path)
net.load_state_dict(pretrained_dict)
# 数据预处理
normMean = [0.49139968, 0.48215827, 0.44653124]
normStd = [0.24703233, 0.24348505, 0.26158768]
normTransform = transforms.Normalize(normMean, normStd)
testTransform = transforms.Compose([
transforms.Resize((32, 32)),
transforms.ToTensor(),
normTransform
])
# 载入数据
test_data = MyDataset(txt_path=txt_path, transform=testTransform)
test_loader = DataLoader(dataset=test_data, batch_size=1)
img, label = iter(test_loader).next()
x = img
writer = SummaryWriter(log_dir=log_dir)
for name, layer in net._modules.items():
# 为fc层预处理x
x = x.view(x.size(0), -1) if "fc" in name else x
# 对x执行单层运算
x = layer(x)
print(x.size())
# 由于__init__()相较于forward()缺少relu操作,需要手动增加
x = F.relu(x) if 'conv' in name else x
# 依据选择的层,进行记录feature maps
if name == vis_layer:
# 绘制feature maps
x1 = x.transpose(0, 1) # C,B, H, W ---> B,C, H, W
img_grid = vutils.make_grid(x1, normalize=True, scale_each=True, nrow=2) # B,C, H, W
writer.add_image(vis_layer + '_feature_maps', img_grid, global_step=666)
# 绘制原始图像
img_raw = normalize_invert(img, normMean, normStd) # 图像去标准化
img_raw = np.array(img_raw * 255).clip(0, 255).squeeze().astype('uint8')
writer.add_image('raw img', img_raw, global_step=666) # j 表示feature map数
writer.close()
================================================
FILE: Code/4_viewer/4_hist_grad_weight.py
================================================
# coding: utf-8
import torch
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
import numpy as np
import os
from torch.autograd import Variable
import torch.nn as nn
import torch.optim as optim
import sys
import os
sys.path.append("..")
from utils.utils import MyDataset, validate, show_confMat, Net
from tensorboardX import SummaryWriter
from datetime import datetime
train_txt_path = os.path.join("..", "..", "Data", "train.txt")
valid_txt_path = os.path.join("..", "..", "Data", "valid.txt")
classes_name = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
train_bs = 16
valid_bs = 16
lr_init = 0.001
max_epoch = 1
# log
log_dir = os.path.join("..", "..", "Result", "hist_grad_weight")
writer = SummaryWriter(log_dir=log_dir)
# ------------------------------------ step 1/4 : 加载数据-------------------------------------------------
# 数据预处理设置
normMean = [0.4948052, 0.48568845, 0.44682974]
normStd = [0.24580306, 0.24236229, 0.2603115]
normTransform = transforms.Normalize(normMean, normStd)
trainTransform = transforms.Compose([
transforms.Resize(32),
transforms.RandomCrop(32, padding=4),
transforms.ToTensor(),
normTransform
])
validTransform = transforms.Compose([
transforms.ToTensor(),
normTransform
])
# 构建MyDataset实例
train_data = MyDataset(txt_path=train_txt_path, transform=trainTransform)
valid_data = MyDataset(txt_path=valid_txt_path, transform=validTransform)
# 构建DataLoder
train_loader = DataLoader(dataset=train_data, batch_size=train_bs, shuffle=True)
valid_loader = DataLoader(dataset=valid_data, batch_size=valid_bs)
# ------------------------------------ step 2/4 : 网络初始化----------------------------------------------
net = Net() # 创建一个网络
net.initialize_weights() # 初始化权值
# ------------------------------------ step 3/4 : 定义损失函数和优化器 ------------------------------------
criterion = nn.CrossEntropyLoss() # 选择损失函数
optimizer = optim.SGD(net.parameters(), lr=lr_init, momentum=0.9, dampening=0.1) # 选择优化器
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=50, gamma=0.1) # 设置学习率下降策略
# ------------------------------------ step 4/4 : 训练 --------------------------------------------------
for epoch in range(max_epoch):
loss_sigma = 0.0 # 记录一个epoch的loss之和
correct = 0.0
total = 0.0
scheduler.step() # 更新学习率
for i, data in enumerate(train_loader):
# 获取图片和标签
inputs, labels = data
inputs, labels = Variable(inputs), Variable(labels)
# forward, backward, update weights
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# 统计预测信息
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).squeeze().sum().numpy()
loss_sigma += loss.item()
# 每10个iteration 打印一次训练信息,loss为10个iteration的平均
if i % 10 == 9:
loss_avg = loss_sigma / 10
loss_sigma = 0.0
print("Training: Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(
epoch + 1, max_epoch, i + 1, len(train_loader), loss_avg, correct / total))
# 每个epoch,记录梯度,权值
for name, layer in net.named_parameters():
writer.add_histogram(name + '_grad', layer.grad.cpu().data.numpy(), epoch)
writer.add_histogram(name + '_data', layer.cpu().data.numpy(), epoch)
print('Finished Training')
================================================
FILE: Code/4_viewer/5_Show_ConfMat.py
================================================
# coding: utf-8
import numpy as np
import os
import matplotlib.pyplot as plt
def show_confMat(confusion_mat, classes_name, set_name, out_dir):
"""
可视化混淆矩阵,保存png格式
:param confusion_mat: nd-array
:param classes_name: list,各类别名称
:param set_name: str, eg: 'valid', 'train'
:param out_dir: str, png输出的文件夹
:return:
"""
# 归一化
confusion_mat_N = confusion_mat.copy()
for i in range(len(classes_name)):
confusion_mat_N[i, :] = confusion_mat[i, :] / confusion_mat[i, :].sum()
# 获取颜色
cmap = plt.cm.get_cmap('Greys') # 更多颜色: http://matplotlib.org/examples/color/colormaps_reference.html
plt.imshow(confusion_mat_N, cmap=cmap)
plt.colorbar()
# 设置文字
xlocations = np.array(range(len(classes_name)))
plt.xticks(xlocations, classes_name, rotation=60)
plt.yticks(xlocations, classes_name)
plt.xlabel('Predict label')
plt.ylabel('True label')
plt.title('Confusion_Matrix_' + set_name)
# 打印数字
for i in range(confusion_mat_N.shape[0]):
for j in range(confusion_mat_N.shape[1]):
plt.text(x=j, y=i, s=int(confusion_mat[i, j]), va='center', ha='center', color='red', fontsize=10)
# 保存
plt.savefig(os.path.join(out_dir, 'Confusion_Matrix_' + set_name + '.png'))
plt.close()
if __name__ == '__main__':
print('QQ group: {} or {} or {} or {}, password: {}'.format(671103375, 773031536, 514974779, 854620826, 2018))
================================================
FILE: Code/4_viewer/6_hook_for_grad_cam.py
================================================
# coding: utf-8
"""
通过实现Grad-CAM学习module中的forward_hook和backward_hook函数
"""
import cv2
import os
import numpy as np
from PIL import Image
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.transforms as transforms
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.pool2 = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool1(F.relu(self.conv1(x)))
x = self.pool1(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
def img_transform(img_in, transform):
"""
将img进行预处理,并转换成模型输入所需的形式—— B*C*H*W
:param img_roi: np.array
:return:
"""
img = img_in.copy()
img = Image.fromarray(np.uint8(img))
img = transform(img)
img = img.unsqueeze(0) # C*H*W --> B*C*H*W
return img
def img_preprocess(img_in):
"""
读取图片,转为模型可读的形式
:param img_in: ndarray, [H, W, C]
:return: PIL.image
"""
img = img_in.copy()
img = cv2.resize(img,(32, 32))
img = img[:, :, ::-1] # BGR --> RGB
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize([0.4948052, 0.48568845, 0.44682974], [0.24580306, 0.24236229, 0.2603115])
])
img_input = img_transform(img, transform)
return img_input
def backward_hook(module, grad_in, grad_out):
grad_block.append(grad_out[0].detach())
def farward_hook(module, input, output):
fmap_block.append(output)
def show_cam_on_image(img, mask, out_dir):
heatmap = cv2.applyColorMap(np.uint8(255*mask), cv2.COLORMAP_JET)
heatmap = np.float32(heatmap) / 255
cam = heatmap + np.float32(img)
cam = cam / np.max(cam)
path_cam_img = os.path.join(out_dir, "cam.jpg")
path_raw_img = os.path.join(out_dir, "raw.jpg")
if not os.path.exists(out_dir):
os.makedirs(out_dir)
cv2.imwrite(path_cam_img, np.uint8(255 * cam))
cv2.imwrite(path_raw_img, np.uint8(255 * img))
def comp_class_vec(ouput_vec, index=None):
"""
计算类向量
:param ouput_vec: tensor
:param index: int,指定类别
:return: tensor
"""
if not index:
index = np.argmax(ouput_vec.cpu().data.numpy())
else:
index = np.array(index)
index = index[np.newaxis, np.newaxis]
index = torch.from_numpy(index)
one_hot = torch.zeros(1, 10).scatter_(1, index, 1)
one_hot.requires_grad = True
class_vec = torch.sum(one_hot * output) # one_hot = 11.8605
return class_vec
def gen_cam(feature_map, grads):
"""
依据梯度和特征图,生成cam
:param feature_map: np.array, in [C, H, W]
:param grads: np.array, in [C, H, W]
:return: np.array, [H, W]
"""
cam = np.zeros(feature_map.shape[1:], dtype=np.float32) # cam shape (H, W)
weights = np.mean(grads, axis=(1, 2)) #
for i, w in enumerate(weights):
cam += w * feature_map[i, :, :]
cam = np.maximum(cam, 0)
cam = cv2.resize(cam, (32, 32))
cam -= np.min(cam)
cam /= np.max(cam)
return cam
if __name__ == '__main__':
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
path_img = os.path.join(BASE_DIR, "..", "..", "Data", "cam_img", "test_img_8.png")
path_net = os.path.join(BASE_DIR, "..", "..", "Data", "net_params_72p.pkl")
output_dir = os.path.join(BASE_DIR, "..", "..", "Result", "backward_hook_cam")
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
fmap_block = list()
grad_block = list()
# 图片读取;网络加载
img = cv2.imread(path_img, 1) # H*W*C
img_input = img_preprocess(img)
net = Net()
net.load_state_dict(torch.load(path_net))
# 注册hook
net.conv2.register_forward_hook(farward_hook)
net.conv2.register_backward_hook(backward_hook)
# forward
output = net(img_input)
idx = np.argmax(output.cpu().data.numpy())
print("predict: {}".format(classes[idx]))
# backward
net.zero_grad()
class_loss = comp_class_vec(output)
class_loss.backward()
# 生成cam
grads_val = grad_block[0].cpu().data.numpy().squeeze()
fmap = fmap_block[0].cpu().data.numpy().squeeze()
cam = gen_cam(fmap, grads_val)
# 保存cam图片
img_show = np.float32(cv2.resize(img, (32, 32))) / 255
show_cam_on_image(img_show, cam, output_dir)
================================================
FILE: Code/main_training/main.py
================================================
# coding: utf-8
import torch
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
import numpy as np
import os
from torch.autograd import Variable
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import sys
sys.path.append("..")
from utils.utils import MyDataset, validate, show_confMat
from tensorboardX import SummaryWriter
from datetime import datetime
train_txt_path = os.path.join("..", "..", "Data", "train.txt")
valid_txt_path = os.path.join("..", "..", "Data", "valid.txt")
classes_name = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
train_bs = 16
valid_bs = 16
lr_init = 0.001
max_epoch = 1
# log
result_dir = os.path.join("..", "..", "Result")
now_time = datetime.now()
time_str = datetime.strftime(now_time, '%m-%d_%H-%M-%S')
log_dir = os.path.join(result_dir, time_str)
if not os.path.exists(log_dir):
os.makedirs(log_dir)
writer = SummaryWriter(log_dir=log_dir)
# ------------------------------------ step 1/5 : 加载数据------------------------------------
# 数据预处理设置
normMean = [0.4948052, 0.48568845, 0.44682974]
normStd = [0.24580306, 0.24236229, 0.2603115]
normTransform = transforms.Normalize(normMean, normStd)
trainTransform = transforms.Compose([
transforms.Resize(32),
transforms.RandomCrop(32, padding=4),
transforms.ToTensor(),
normTransform
])
validTransform = transforms.Compose([
transforms.ToTensor(),
normTransform
])
# 构建MyDataset实例
train_data = MyDataset(txt_path=train_txt_path, transform=trainTransform)
valid_data = MyDataset(txt_path=valid_txt_path, transform=validTransform)
# 构建DataLoder
train_loader = DataLoader(dataset=train_data, batch_size=train_bs, shuffle=True)
valid_loader = DataLoader(dataset=valid_data, batch_size=valid_bs)
# ------------------------------------ step 2/5 : 定义网络------------------------------------
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.pool2 = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool1(F.relu(self.conv1(x)))
x = self.pool2(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
# 定义权值初始化
def initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
torch.nn.init.xavier_normal_(m.weight.data)
if m.bias is not None:
m.bias.data.zero_()
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
elif isinstance(m, nn.Linear):
torch.nn.init.normal_(m.weight.data, 0, 0.01)
m.bias.data.zero_()
net = Net() # 创建一个网络
net.initialize_weights() # 初始化权值
# ------------------------------------ step 3/5 : 定义损失函数和优化器 ------------------------------------
criterion = nn.CrossEntropyLoss() # 选择损失函数
optimizer = optim.SGD(net.parameters(), lr=lr_init, momentum=0.9, dampening=0.1) # 选择优化器
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=50, gamma=0.1) # 设置学习率下降策略
# ------------------------------------ step 4/5 : 训练 --------------------------------------------------
for epoch in range(max_epoch):
loss_sigma = 0.0 # 记录一个epoch的loss之和
correct = 0.0
total = 0.0
scheduler.step() # 更新学习率
for i, data in enumerate(train_loader):
# if i == 30 : break
# 获取图片和标签
inputs, labels = data
inputs, labels = Variable(inputs), Variable(labels)
# forward, backward, update weights
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# 统计预测信息
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).squeeze().sum().numpy()
loss_sigma += loss.item()
# 每10个iteration 打印一次训练信息,loss为10个iteration的平均
if i % 10 == 9:
loss_avg = loss_sigma / 10
loss_sigma = 0.0
print("Training: Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(
epoch + 1, max_epoch, i + 1, len(train_loader), loss_avg, correct / total))
# 记录训练loss
writer.add_scalars('Loss_group', {'train_loss': loss_avg}, epoch)
# 记录learning rate
writer.add_scalar('learning rate', scheduler.get_lr()[0], epoch)
# 记录Accuracy
writer.add_scalars('Accuracy_group', {'train_acc': correct / total}, epoch)
# 每个epoch,记录梯度,权值
for name, layer in net.named_parameters():
writer.add_histogram(name + '_grad', layer.grad.cpu().data.numpy(), epoch)
writer.add_histogram(name + '_data', layer.cpu().data.numpy(), epoch)
# ------------------------------------ 观察模型在验证集上的表现 ------------------------------------
if epoch % 2 == 0:
loss_sigma = 0.0
cls_num = len(classes_name)
conf_mat = np.zeros([cls_num, cls_num]) # 混淆矩阵
net.eval()
for i, data in enumerate(valid_loader):
# 获取图片和标签
images, labels = data
images, labels = Variable(images), Variable(labels)
# forward
outputs = net(images)
outputs.detach_()
# 计算loss
loss = criterion(outputs, labels)
loss_sigma += loss.item()
# 统计
_, predicted = torch.max(outputs.data, 1)
# labels = labels.data # Variable --> tensor
# 统计混淆矩阵
for j in range(len(labels)):
cate_i = labels[j].numpy()
pre_i = predicted[j].numpy()
conf_mat[cate_i, pre_i] += 1.0
print('{} set Accuracy:{:.2%}'.format('Valid', conf_mat.trace() / conf_mat.sum()))
# 记录Loss, accuracy
writer.add_scalars('Loss_group', {'valid_loss': loss_sigma / len(valid_loader)}, epoch)
writer.add_scalars('Accuracy_group', {'valid_acc': conf_mat.trace() / conf_mat.sum()}, epoch)
print('Finished Training')
# ------------------------------------ step5: 保存模型 并且绘制混淆矩阵图 ------------------------------------
net_save_path = os.path.join(log_dir, 'net_params.pkl')
torch.save(net.state_dict(), net_save_path)
conf_mat_train, train_acc = validate(net, train_loader, 'train', classes_name)
conf_mat_valid, valid_acc = validate(net, valid_loader, 'valid', classes_name)
show_confMat(conf_mat_train, classes_name, 'train', log_dir)
show_confMat(conf_mat_valid, classes_name, 'valid', log_dir)
================================================
FILE: Code/utils/__init__.py
================================================
================================================
FILE: Code/utils/utils.py
================================================
# coding: utf-8
from PIL import Image
from torch.utils.data import Dataset
import numpy as np
import torch
from torch.autograd import Variable
import os
import matplotlib.pyplot as plt
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.pool2 = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool1(F.relu(self.conv1(x)))
x = self.pool2(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
# 定义权值初始化
def initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
torch.nn.init.xavier_normal_(m.weight.data)
if m.bias is not None:
m.bias.data.zero_()
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
elif isinstance(m, nn.Linear):
torch.nn.init.normal_(m.weight.data, 0, 0.01)
m.bias.data.zero_()
class MyDataset(Dataset):
def __init__(self, txt_path, transform = None, target_transform = None):
fh = open(txt_path, 'r')
imgs = []
for line in fh:
line = line.rstrip()
words = line.split()
imgs.append((words[0], int(words[1])))
self.imgs = imgs # 最主要就是要生成这个list, 然后DataLoader中给index,通过getitem读取图片数据
self.transform = transform
self.target_transform = target_transform
def __getitem__(self, index):
fn, label = self.imgs[index]
img = Image.open(fn).convert('RGB') # 像素值 0~255,在transfrom.totensor会除以255,使像素值变成 0~1
if self.transform is not None:
img = self.transform(img) # 在这里做transform,转为tensor等等
return img, label
def __len__(self):
return len(self.imgs)
def validate(net, data_loader, set_name, classes_name):
"""
对一批数据进行预测,返回混淆矩阵以及Accuracy
:param net:
:param data_loader:
:param set_name: eg: 'valid' 'train' 'tesst
:param classes_name:
:return:
"""
net.eval()
cls_num = len(classes_name)
conf_mat = np.zeros([cls_num, cls_num])
for data in data_loader:
images, labels = data
images = Variable(images)
labels = Variable(labels)
outputs = net(images)
outputs.detach_()
_, predicted = torch.max(outputs.data, 1)
# 统计混淆矩阵
for i in range(len(labels)):
cate_i = labels[i].numpy()
pre_i = predicted[i].numpy()
conf_mat[cate_i, pre_i] += 1.0
for i in range(cls_num):
print('class:{:<10}, total num:{:<6}, correct num:{:<5} Recall: {:.2%} Precision: {:.2%}'.format(
classes_name[i], np.sum(conf_mat[i, :]), conf_mat[i, i], conf_mat[i, i] / (1 + np.sum(conf_mat[i, :])),
conf_mat[i, i] / (1 + np.sum(conf_mat[:, i]))))
print('{} set Accuracy:{:.2%}'.format(set_name, np.trace(conf_mat) / np.sum(conf_mat)))
return conf_mat, '{:.2}'.format(np.trace(conf_mat) / np.sum(conf_mat))
def show_confMat(confusion_mat, classes, set_name, out_dir):
# 归一化
confusion_mat_N = confusion_mat.copy()
for i in range(len(classes)):
confusion_mat_N[i, :] = confusion_mat[i, :] / confusion_mat[i, :].sum()
# 获取颜色
cmap = plt.cm.get_cmap('Greys') # 更多颜色: http://matplotlib.org/examples/color/colormaps_reference.html
plt.imshow(confusion_mat_N, cmap=cmap)
plt.colorbar()
# 设置文字
xlocations = np.array(range(len(classes)))
plt.xticks(xlocations, list(classes), rotation=60)
plt.yticks(xlocations, list(classes))
plt.xlabel('Predict label')
plt.ylabel('True label')
plt.title('Confusion_Matrix_' + set_name)
# 打印数字
for i in range(confusion_mat_N.shape[0]):
for j in range(confusion_mat_N.shape[1]):
plt.text(x=j, y=i, s=int(confusion_mat[i, j]), va='center', ha='center', color='red', fontsize=10)
# 保存
plt.savefig(os.path.join(out_dir, 'Confusion_Matrix' + set_name + '.png'))
plt.close()
def normalize_invert(tensor, mean, std):
for t, m, s in zip(tensor, mean, std):
t.mul_(s).add_(m)
return tensor
================================================
FILE: Data/visual.txt
================================================
../../Data/cat.png 3
================================================
FILE: readme.md
================================================
# Pytorch模型训练实用教程
<img src="./Data/cover.png" alt="Image text" style="zoom:33%;" />
---
📢:《PyTorch实用教程》(第二版)已开源,欢迎阅读:https://tingsongyu.github.io/PyTorch-Tutorial-2nd/
📢:《PyTorch实用教程》(第二版)已开源,欢迎阅读:https://tingsongyu.github.io/PyTorch-Tutorial-2nd/
📢:《PyTorch实用教程》(第二版)已开源,欢迎阅读:https://tingsongyu.github.io/PyTorch-Tutorial-2nd/
第二版新增丰富的**深度学习应用案例**和**推理部署框架**,包括CV、NLP和LLM的十多个实战项目,以及ONNX和TensorRT的教程。
# 1.简介
本代码为教程——《Pytorch模型训练实用教程》中配套代码;<br/>
《Pytorch模型训练实用教程》可通过如下方式获取:<br/>
1. https://github.com/tensor-yu/PyTorch_Tutorial/tree/master/Data<br/>
2. QQ群: 四群:854620826 <br/>
# 2.环境配置
代码在以下两种环境测试过:<br/>
1. win10 64位 + python3.5 + pytorch==0.4.0 <br/>
2. mac + python3.6 + pytorch==0.4.1/ pytorch==1.0.0 <br/>
**第一步 安装各依赖包:**<br/>
pip install -r requirements.txt
**第二步 手动安装pytorch及torchvision:**<br/>
均选择无gpu版本进行安装,进入官网选择相应的指令进行安装
https://pytorch.org/get-started/locally/
# 3.问题反馈
若发现任何问题和改进意见,请您随时联系我。<br/>
联系方式:yts3221@126.com<br/>
读者qq群:
一群:671103375 (已满) <br/>
二群:773031536 (已满)<br/>
三群:514974779 (已满)<br/>
四群:854620826(已满)
五群:1021300804
# 4.修改记录
0.0.5:
1. 1.6小节勘误,将36\*36改为40\*40;
2. 2.3小节删除注释;
3. 修改权值初始化杂谈中的理解错误;
4. 全文代码缩进。
---
如果本教程对你有帮助😀😀,请作者喝杯茶吧🍵🍵🥂🥂
WeChat:<img src="https://img.picgo.net/2024/05/18/wechat2859fc4f155e9302.jpg" style="width:20%;"/> Alipay:<img src="https://img.picgo.net/2024/05/18/alipayd96d6d0a325ef7e0.jpg" style="width:20%;"/>
---
## Stargazers over time
[](https://starchart.cc/TingsongYu/PyTorch_Tutorial)
================================================
FILE: requirements.txt
================================================
absl-py==0.6.1
astor==0.7.1
cycler==0.10.0
gast==0.2.0
grpcio==1.16.0
h5py==2.8.0
Keras-Applications==1.0.6
Keras-Preprocessing==1.0.5
kiwisolver==1.0.1
Markdown==3.0.1
matplotlib==2.2.3
numpy==1.15.1
opencv-python==3.4.3.18
Pillow==5.2.0
protobuf==3.6.1
pyparsing==2.2.0
python-dateutil==2.7.3
pytz==2018.5
scipy==1.1.0
six==1.11.0
tensorboard==1.12.0
tensorboardX==1.4
tensorflow==1.12.0
termcolor==1.1.0
Werkzeug==0.14.1
gitextract_lx1nh74y/ ├── .gitignore ├── Code/ │ ├── 1_data_prepare/ │ │ ├── 1_1_cifar10_to_png.py │ │ ├── 1_2_split_dataset.py │ │ ├── 1_3_generate_txt.py │ │ ├── 1_3_mydataset.py │ │ └── 1_5_compute_mean.py │ ├── 2_model/ │ │ ├── 2_finetune.py │ │ └── net_params.pkl │ ├── 3_optimizer/ │ │ ├── 3_1_lossFunction/ │ │ │ ├── 1_L1Loss.py │ │ │ ├── 2_MSELoss.py │ │ │ ├── 3_CrossEntropyLoss.py │ │ │ ├── 4_NLLLoss.py │ │ │ ├── 5_PoissonNLLLoss.py │ │ │ └── 6_KLDivLoss.py │ │ └── 3_2_optimizer/ │ │ ├── 1_param_groups.py │ │ ├── 2_zero_grad.py │ │ ├── 3_state_dict.py │ │ ├── 4_load_state_dict.py │ │ ├── 5_add_param_group.py │ │ └── net_params.pkl │ ├── 4_viewer/ │ │ ├── 1_tensorboardX_demo.py │ │ ├── 2_visual_weights.py │ │ ├── 3_visual_featuremaps.py │ │ ├── 4_hist_grad_weight.py │ │ ├── 5_Show_ConfMat.py │ │ └── 6_hook_for_grad_cam.py │ ├── main_training/ │ │ └── main.py │ └── utils/ │ ├── __init__.py │ └── utils.py ├── Data/ │ ├── net_params_72p.pkl │ └── visual.txt ├── readme.md └── requirements.txt
SYMBOL INDEX (49 symbols across 12 files)
FILE: Code/1_data_prepare/1_1_cifar10_to_png.py
function unpickle (line 20) | def unpickle(file):
function my_mkdir (line 25) | def my_mkdir(my_dir):
FILE: Code/1_data_prepare/1_2_split_dataset.py
function makedir (line 21) | def makedir(new_dir):
FILE: Code/1_data_prepare/1_3_generate_txt.py
function gen_txt (line 14) | def gen_txt(txt_path, img_dir):
FILE: Code/1_data_prepare/1_3_mydataset.py
class MyDataset (line 6) | class MyDataset(Dataset):
method __init__ (line 7) | def __init__(self, txt_path, transform=None, target_transform=None):
method __getitem__ (line 19) | def __getitem__(self, index):
method __len__ (line 28) | def __len__(self):
FILE: Code/2_model/2_finetune.py
class Net (line 66) | class Net(nn.Module):
method __init__ (line 67) | def __init__(self):
method forward (line 77) | def forward(self, x):
method initialize_weights (line 87) | def initialize_weights(self):
FILE: Code/3_optimizer/3_2_optimizer/3_state_dict.py
class Net (line 8) | class Net(nn.Module):
method __init__ (line 9) | def __init__(self):
method forward (line 15) | def forward(self, x):
FILE: Code/3_optimizer/3_2_optimizer/4_load_state_dict.py
class Net (line 10) | class Net(nn.Module):
method __init__ (line 11) | def __init__(self):
method forward (line 17) | def forward(self, x):
method zero_param (line 23) | def zero_param(self):
FILE: Code/4_viewer/2_visual_weights.py
class Net (line 10) | class Net(nn.Module):
method __init__ (line 11) | def __init__(self):
method forward (line 21) | def forward(self, x):
method initialize_weights (line 31) | def initialize_weights(self):
FILE: Code/4_viewer/5_Show_ConfMat.py
function show_confMat (line 8) | def show_confMat(confusion_mat, classes_name, set_name, out_dir):
FILE: Code/4_viewer/6_hook_for_grad_cam.py
class Net (line 15) | class Net(nn.Module):
method __init__ (line 16) | def __init__(self):
method forward (line 26) | def forward(self, x):
function img_transform (line 36) | def img_transform(img_in, transform):
function img_preprocess (line 49) | def img_preprocess(img_in):
function backward_hook (line 66) | def backward_hook(module, grad_in, grad_out):
function farward_hook (line 70) | def farward_hook(module, input, output):
function show_cam_on_image (line 74) | def show_cam_on_image(img, mask, out_dir):
function comp_class_vec (line 88) | def comp_class_vec(ouput_vec, index=None):
function gen_cam (line 108) | def gen_cam(feature_map, grads):
FILE: Code/main_training/main.py
class Net (line 69) | class Net(nn.Module):
method __init__ (line 70) | def __init__(self):
method forward (line 80) | def forward(self, x):
method initialize_weights (line 90) | def initialize_weights(self):
FILE: Code/utils/utils.py
class Net (line 13) | class Net(nn.Module):
method __init__ (line 14) | def __init__(self):
method forward (line 24) | def forward(self, x):
method initialize_weights (line 34) | def initialize_weights(self):
class MyDataset (line 47) | class MyDataset(Dataset):
method __init__ (line 48) | def __init__(self, txt_path, transform = None, target_transform = None):
method __getitem__ (line 60) | def __getitem__(self, index):
method __len__ (line 69) | def __len__(self):
function validate (line 73) | def validate(net, data_loader, set_name, classes_name):
function show_confMat (line 112) | def show_confMat(confusion_mat, classes, set_name, out_dir):
function normalize_invert (line 141) | def normalize_invert(tensor, mean, std):
Condensed preview — 33 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (59K chars).
[
{
"path": ".gitignore",
"chars": 43,
"preview": "*.py[cod]\n*.so\n*.egg\n*.egg-info\n*.DS_Store\n"
},
{
"path": "Code/1_data_prepare/1_1_cifar10_to_png.py",
"chars": 2071,
"preview": "# coding:utf-8\n\"\"\"\n 将cifar10的data_batch_12345 转换成 png格式的图片\n 每个类别单独存放在一个文件夹,文件夹名称为0-9\n\"\"\"\nfrom imageio import imwri"
},
{
"path": "Code/1_data_prepare/1_2_split_dataset.py",
"chars": 1490,
"preview": "# coding: utf-8\n\"\"\"\n 将原始数据集进行划分成训练集、验证集和测试集\n\"\"\"\n\nimport os\nimport glob\nimport random\nimport shutil\n\ndataset_dir = os."
},
{
"path": "Code/1_data_prepare/1_3_generate_txt.py",
"chars": 1084,
"preview": "# coding:utf-8\nimport os\n'''\n 为数据集生成对应的txt文件\n'''\n\ntrain_txt_path = os.path.join(\"..\", \"..\", \"Data\", \"train.txt\")\ntrai"
},
{
"path": "Code/1_data_prepare/1_3_mydataset.py",
"chars": 895,
"preview": "# coding: utf-8\nfrom PIL import Image\nfrom torch.utils.data import Dataset\n\n\nclass MyDataset(Dataset):\n def __init__("
},
{
"path": "Code/1_data_prepare/1_5_compute_mean.py",
"chars": 1070,
"preview": "# coding: utf-8\n\nimport numpy as np\nimport cv2\nimport random\nimport os\n\n\"\"\"\n 随机挑选CNum张图片,进行按通道计算均值mean和标准差std\n 先将像"
},
{
"path": "Code/2_model/2_finetune.py",
"chars": 6707,
"preview": "# coding: utf-8\n\nimport torch\nfrom torch.utils.data import DataLoader\nimport torchvision.transforms as transforms\nimport"
},
{
"path": "Code/3_optimizer/3_1_lossFunction/1_L1Loss.py",
"chars": 669,
"preview": "# coding: utf-8\n\nimport torch\nimport torch.nn as nn\n\n# ----------------------------------- L1 Loss\n\n# 生成网络输出 以及 目标输出\nout"
},
{
"path": "Code/3_optimizer/3_1_lossFunction/2_MSELoss.py",
"chars": 676,
"preview": "# coding: utf-8\n\nimport torch\nimport torch.nn as nn\n\n# ----------------------------------- MSE loss\n\n# 生成网络输出 以及 目标输出\nou"
},
{
"path": "Code/3_optimizer/3_1_lossFunction/3_CrossEntropyLoss.py",
"chars": 2336,
"preview": "# coding: utf-8\n\nimport torch\nimport torch.nn as nn\nimport numpy as np\nimport math\n\n# ----------------------------------"
},
{
"path": "Code/3_optimizer/3_1_lossFunction/4_NLLLoss.py",
"chars": 635,
"preview": "# coding: utf-8\n\nimport torch\nimport torch.nn as nn\nimport numpy as np\n\n# ----------------------------------- log likeli"
},
{
"path": "Code/3_optimizer/3_1_lossFunction/5_PoissonNLLLoss.py",
"chars": 311,
"preview": "# coding: utf-8\n\nimport torch\nimport torch.nn as nn\nimport numpy as np\n\n# ----------------------------------- Poisson NL"
},
{
"path": "Code/3_optimizer/3_1_lossFunction/6_KLDivLoss.py",
"chars": 825,
"preview": "# coding: utf-8\n\nimport torch\nimport torch.nn as nn\nimport numpy as np\n\n# ----------------------------------- KLDiv los"
},
{
"path": "Code/3_optimizer/3_2_optimizer/1_param_groups.py",
"chars": 580,
"preview": "# coding: utf-8\n\nimport torch\nimport torch.optim as optim\n\n\nw1 = torch.randn(2, 2)\nw1.requires_grad = True\n\nw2 = torch.r"
},
{
"path": "Code/3_optimizer/3_2_optimizer/2_zero_grad.py",
"chars": 549,
"preview": "# coding: utf-8\n\nimport torch\nimport torch.optim as optim\n\n# ----------------------------------- zero_grad\n\nw1 = torch.r"
},
{
"path": "Code/3_optimizer/3_2_optimizer/3_state_dict.py",
"chars": 735,
"preview": "# coding: utf-8\n\nimport torch.nn as nn\nimport torch.nn.functional as F\n\n\n# ----------------------------------- state_dic"
},
{
"path": "Code/3_optimizer/3_2_optimizer/4_load_state_dict.py",
"chars": 1278,
"preview": "# coding: utf-8\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\n\n# --------------------------------"
},
{
"path": "Code/3_optimizer/3_2_optimizer/5_add_param_group.py",
"chars": 676,
"preview": "# coding: utf-8\n\nimport torch\nimport torch.optim as optim\n\n# ----------------------------------- add_param_group\n\nw1 = t"
},
{
"path": "Code/4_viewer/1_tensorboardX_demo.py",
"chars": 4054,
"preview": "# coding: utf-8\nimport os\nimport torch\nimport torchvision.utils as vutils\nimport numpy as np\nimport torchvision.models a"
},
{
"path": "Code/4_viewer/2_visual_weights.py",
"chars": 2480,
"preview": "# coding: utf-8\nimport os\nimport torch\nimport torchvision.utils as vutils\nfrom tensorboardX import SummaryWriter\nimport "
},
{
"path": "Code/4_viewer/3_visual_featuremaps.py",
"chars": 1984,
"preview": "# coding: utf-8\nimport os\nimport torch\nimport torchvision.utils as vutils\nimport numpy as np\nfrom tensorboardX import Su"
},
{
"path": "Code/4_viewer/4_hist_grad_weight.py",
"chars": 3580,
"preview": "# coding: utf-8\n\nimport torch\nfrom torch.utils.data import DataLoader\nimport torchvision.transforms as transforms\nimport"
},
{
"path": "Code/4_viewer/5_Show_ConfMat.py",
"chars": 1436,
"preview": "# coding: utf-8\nimport numpy as np\nimport os\nimport matplotlib.pyplot as plt\n\n\n\ndef show_confMat(confusion_mat, classes_"
},
{
"path": "Code/4_viewer/6_hook_for_grad_cam.py",
"chars": 4621,
"preview": "# coding: utf-8\n\"\"\"\n通过实现Grad-CAM学习module中的forward_hook和backward_hook函数\n\"\"\"\nimport cv2\nimport os\nimport numpy as np\nfrom "
},
{
"path": "Code/main_training/main.py",
"chars": 6987,
"preview": "# coding: utf-8\n\nimport torch\nfrom torch.utils.data import DataLoader\nimport torchvision.transforms as transforms\nimport"
},
{
"path": "Code/utils/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "Code/utils/utils.py",
"chars": 4613,
"preview": "# coding: utf-8\nfrom PIL import Image\nfrom torch.utils.data import Dataset\nimport numpy as np\nimport torch\nfrom torch.au"
},
{
"path": "Data/visual.txt",
"chars": 20,
"preview": "../../Data/cat.png 3"
},
{
"path": "readme.md",
"chars": 1583,
"preview": "# Pytorch模型训练实用教程\n<img src=\"./Data/cover.png\" alt=\"Image text\" style=\"zoom:33%;\" />\n\n---\n\n📢:《PyTorch实用教程》(第二版)已开源,欢迎阅读:"
},
{
"path": "requirements.txt",
"chars": 424,
"preview": "absl-py==0.6.1\nastor==0.7.1\ncycler==0.10.0\ngast==0.2.0\ngrpcio==1.16.0\nh5py==2.8.0\nKeras-Applications==1.0.6\nKeras-Prepro"
}
]
// ... and 3 more files (download for full content)
About this extraction
This page contains the full source code of the TingsongYu/PyTorch_Tutorial GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 33 files (53.1 KB), approximately 17.2k tokens, and a symbol index with 49 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.