实现进度条效果,不在是每次更新则是输出一条信息提示:、
for i, (image, segment_image) in enumerate(data_loader):
import tqdm
for i, (image, segment_image) in enumerate(tqdm.tqdm(data_loader)):
CUDA和pytorch版本对应的铁汁:
显卡驱动与CUDA关系图:
pytorch查看GPU安装情况:
import torch
print(torch.__version__) # 查看torch当前版本号
print(torch.version.cuda) # 编译当前版本的torch使用的cuda版本号
print(torch.cuda.is_available()) # 查看当前cuda是否可用于当前版本的Torch,如果输出True,则表示可用
指定pytorch-CUDA版本的pip安装
# CUDA 10.1
pip install torch==1.4.0 torchvision==0.5.0
# CUDA 9.2
pip install torch==1.4.0+cu92 torchvision==0.5.0+cu92 -f https://download.pytorch.org/whl/torch_stable.html
# CPU only
pip install torch==1.4.0+cpu torchvision==0.5.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
安装指定库
url可选:
阿里云 http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣(douban) http://pypi.douban.com/simple/
清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/
即 pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple/
pip install 包名 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
查看CUDA和torch版本
import torch
print(torch.cuda.device_count())
print(torch.cuda.is_available())
print(torch.version.cuda)
本地用conda安装库
conda install --use-local 库.tar.bz2
安装TensorFlow-gpu版本:
Tensorflow与Python、CUDA、cuDNN的版本对应表_tensorflow版本对应python3.11-CSDN博客
画图时:对于Tensor数据类型时描点,其中model是放入CUDA的模型
a = np.arange(0,10,0.5).reshape([20,1])
a = torch.FloatTensor(a)
b = model(a.cuda()).cpu()
plt.plot(a.numpy(), b.data.numpy(), 'r.')
a为Tensor类型,所以画图时转为numpy时只需+.numpy(),而b是model模型输出的所以转为numpy时只需+.data.numpy()
或者data.cpu().numpy()
unsqueeze(1)用法:其实就是转置(好像并不是转置,只是删去了某个维度)
x = torch.randn(batch_size)
***************************
tensor([-0.3597, 0.1055, 1.8233])
***************************
x = x.unsqueeze(1)
***************************
tensor([[-0.3597],
[ 0.1055],
[ 1.8233]])
***************************
toech.nn.Sequential相当于是一个盒子,能把自定义的一些运算加进去,比如:
self.layer=nn.Sequential(
nn.Conv2d(in_channel,out_channel,3,1,1,padding_mode='reflect',bias=False),
nn.BatchNorm2d(out_channel),
nn.Dropout2d(0.3),
nn.LeakyReLU(),
nn.Conv2d(out_channel, out_channel, 3, 1, 1,adding_mode='reflect', bias=False),
nn.BatchNorm2d(out_channel),
nn.Dropout2d(0.3),
nn.LeakyReLU()
)
Batch_Normalization层应该在全连接层后面,非线性层之前
.max()用法,将Tensor数组中的最大值和索引输出:
out = model(train_img)
print(out.shape)
print(out[0])
a, b = out[0].max(1)
print(a)
print(b)
************************输出***************************
torch.Size([32, 1, 10])
tensor([[-0.1235, 0.1564, 0.0388, -0.3688, -0.0031, 0.0962, -0.0308, 0.1271,
0.1062, -0.1925]], device='cuda:0', grad_fn=<SelectBackward>)
tensor([0.1564], device='cuda:0', grad_fn=<MaxBackward0>)
tensor([1], device='cuda:0')
max(0)是输出列中最大,max(1)输出行最大,其实他这个就是按照数组的维度来算的。假如一个数组为
a.shape = 3,1,2
a = [[[1,2]],
[[3,4]],
[[5,6]]]
若求max(0),则为:【5,6】
若求max(2),则为:【2,4,6】
添加时间记录:
import time
start = time.time()
***
***
***
during = time.time() - start
print()
print('During Time: {:.3f} s'.format(during))
降维操作:
假设img维数为【32,1,28,28】
print(img.shape)
****************************
torch.Size([16, 1, 28, 28])
方法一:
img = torch.reshape(img,(32,-1))
******************************
torch.Size([32, 784])
方法二:
img = img.squeeze(1)
********************************
torch.Size([32, 28, 28])
方法三:
img = img.view(img.size(0), -1)
******************************
torch.Size([32, 784])
卷积操作,为了使输入等于输出,一般来说,当步长S=1时,填充P=,其中F为卷积和的大小
nn.CrossEntropyLoss()交叉熵损失函数
##此函数,好像是输入【通道数,类别种类的概率】,标签【通道数,所属类别数字】
否则容易报错
a = nn.CrossEntropyLoss()
loss = a(out, lable)
其中
out.shape:torch.Size([32, 10])
tensor([[-9.2298e-01, -5.6865e-03, -7.2597e-02, -4.5078e-01, 9.9050e-01,
-4.0623e-02, 2.2258e-01, 4.2107e-01, -3.3298e-01, 1.2533e-01],.........
label.shape:torch.Size([32])
tensor([5, 0, 4, 1, 9, 2, 1, 3, 1, 4, 3, 5, 3, 6, 1, 7, 2, 8, 6, 9, 4, 0, 9, 1,
1, 2, 4, 3, 2, 7, 3, 8], device='cuda:0')
CrossEntropyLoss = softmax + log + NLLLoss
其中:
softmax:将图片(每行)的类别(每列),规范到每一行的值加起来都等于1,即范围【0,1】
log: 对其求log,即范围在【-无穷,0】
NLLLoss:每个图片(每行)的标签所选的绝对值相加再求平均
参考:Pytorch中Softmax、Log_Softmax、NLLLoss以及CrossEntropyLoss的关系与区别详解_AI学渣的博客-CSDN博客
nn.Sequential()的几种用法:
用法一:
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
layer1 = nn.Sequential()
layer1.add_module('conv1', nn.Conv2d(3,32,3, 1, 1))
layer1.add_module('relu1', nn.ReLU(True))
layer1.add_module('pool1', nn.MaxPool2d(2,2))
self.layer1 = layer1
用法二:
class Batch_Net(nn.Module):
def __init__(self, in_dim, out_dim, n_hidden_1, n_hidden_2):
super(Batch_Net, self).__init__()
self.layer1 = nn.Sequential(
nn.Linear(in_dim, n_hidden_1),
nn.BatchNorm1d(n_hidden_1),
nn.ReLU(True)
)
nn.Linear
(输入数, 输出数),线性函数,只能输入1维的数据(也就是所有的数据都得在同一个维度),例如:【1,1, 25】,但是【1,5, 5】就会报错了
通道换位置:
python读取图片后,图片的矩阵位置是【长,宽,通道】,想换成【通道,长,宽】
则利用np.transpose
im = cv2.imread('./cat.png')
cv2.imshow('xx',im)
cv2.waitKey(0)
cv2.destroyAllWindows()
im = np.array(im)
im = np.transpose(im, (2, 0, 1))
## 方法2
x = x.permute(0,2,1)
卷积nn.Conv2d()输入的是float型数据(应该是这个吧),否则会报错,卷积不了
报错版本:
a = nn.Conv2d(1, 1, 3)
im = a(im)
print(im.type())
****************************************************
torch.ByteTensor
报错:RuntimeError: expected scalar type Byte but found Float
正确版本:
a = nn.Conv2d(1, 1, 3)
im = a(im。float())
print(im.type())
************************************
torch.FloatTensor
torchvision.transforms图像增强的用法:
第一个函数是 scale,对图片的尺度进行缩小和放大
第二个函数是 centerCrop,对图像正中心进行给定大小的裁剪;
第三个函数是Randomcrop,对图片进行给定大小的随机裁剪;
第四个函数是 RandomHorizaontalFIip,对图片进行概率为0.5的随机水平翻转;
第五个函数是 RandomSizedcrop,首先对图片进行随机尺寸的裁剪,然后对裁剪的图片进行一个随机比例的缩放,最后将图片变成给定的大小,这在InceptionNet 中比较流行;
最后一个是 pad,对图片进行边界零填充。
torch.stack()用法:他只能拼凑单张图片,不能用多张已经拼凑的图片来拼凑
举例MNIST手写体数据集,因为我设定batch_size为32,所以ima和pic都是32张拼凑成的图,所以用torch.stack()回报错:
RuntimeError: output with shape [32, 1, 28] doesn't match the broadcast shape [32, 32, 28, 28]
错误代码:
img = torch.stack([ima, pic], dim=0)
正确代码:
img = torch.stack([ima[0], pic[0]], dim=0)
np.setdiff1d(a,b)筛选掉a中有b的部分
panda.sort_values(‘xx’)指定表格以XX列为顺序排列
panda.drop('xx')删除XX列
x.clamp(a, b):限制x数组的大小在a,b之间
nn.BCELoss()的标签输入应该是没有梯度的,若有梯度存在则会报错
## 查看梯度
print(label.requires_grad)
## 删除梯度
label.detach()
批量修改图片文件名:
原因标签的名字和原图名字不同,标签名后面带有一些小尾巴,把尾巴割掉
a = 'D:\\test\\Python\\unet\\train1\\data\\head\\'
b = os.listdir(os.path.join(a, 'labels'))
# print(b)
n = 0
for i in b:
# 设置旧文件名(就是路径+文件名)
oldname = a + 'labels' + os.sep + b[n]
## 文件前面的名字
prename = b[n].split('-')[0]
# 设置新文件名
newname = a + 'labels' + os.sep + prename + '.JPG'
os.rename(oldname, newname) # 用os模块中的rename方法对文件改名
print(oldname, '======>', newname)
n += 1
查看torch.utils.data。 DataLoader里面的数据
train_data.__iter__().next()[0]
标签求边缘和像素:
mask = (im>= 0) & (im< 1)
mask = (im>= 0) & (im< 21)
a = im[mask].astype('int')
'''
其中im为【513,513】numpy类型的
a=【40398】
'''
图从左到右为:源图,<1 , <21
查看torch的数据类型:A.dtype
数据的维度换位置
tmpImg = tmpImg.transpose((2, 0, 1))
更新优化函数的学习率:
from torch.optim.lr_scheduler import _LRScheduler
class PolynomialLR(_LRScheduler):
def __init__(self, optimizer, step_size, iter_max, power, last_epoch=-1):
self.step_size = step_size
self.iter_max = iter_max
self.power = power
super(PolynomialLR, self).__init__(optimizer, last_epoch)
def polynomial_decay(self, lr):
return lr * (1 - float(self.last_epoch) / self.iter_max) ** self.power
def get_lr(self):
if (
(self.last_epoch == 0)
or (self.last_epoch % self.step_size != 0)
or (self.last_epoch > self.iter_max)
):
return [group["lr"] for group in self.optimizer.param_groups]
return [self.polynomial_decay(lr) for lr in self.base_lrs]
scheduler = PolynomialLR(
optimizer=optimizer,
step_size=1,
iter_max=20,
power=0.9,
)
for for epoch in train:
scheduler.step(epoch=epoch)
平均损失率:
losses_men = []
acces_men = []
for epoche in range(epoches):
train_loss = 0
train_acc = 0
for image_data, image_label in tqdm.tqdm(train_data) :
##记录误差
train_loss += loss.item()
##记录准确率
_,pred_label = out.max(1)
num_correct = (pred_label == image_label).sum().item() ##计算每次batch_size正确的个数
acc = num_correct / out.shape[0]
train_acc += acc
losses_men.append(train_loss / len(train_data) )
losses_men.append(train_loss / len(train_data) )
显示pytorch格式的图片:
from torchvision.transforms import transforms
to_pil_image = transforms.ToPILImage()
img = to_pil_image(image[0])
img.show()
plt.figure("visualize", (8, 8))
plt.subplot(2, 2, 1)
plt.title("image")
plt.imshow(image[:, :, 30], cmap="gray")
plt.subplot(2, 2, 2)
plt.title("label")
plt.imshow(label[:, :, 30])
plt.subplot(2, 2, 3)
plt.title("dealed image")
plt.imshow(imagecrop[:, :, 15], cmap="gray")
plt.subplot(2, 2, 4)
plt.title("dealed label")
plt.imshow(labelcrop[:, :, 15])
plt.show()
## 显示2*2的图像
数据类型问题:
CV显示时用的是uint8的类型所以得转:
label = np.array(label,dtype='uint8')
cv2.imshow('1', label)
Tensor显示图片时,用的是float32类型的
to_pil_image = transforms.ToPILImage()
a = torch.tensor(labels, dtype=torch.float32)
img = to_pil_image(a)
img.show()
统计Tensor里的元素个数:
torch.unique(labels[0],return_counts=True)
把损失函数写入Excel表格里
a = []
b = []
c = []
epo = []
def data_write(file_path,epoch, datas1, datas2, datas3):#datas是列表
# print(datas)
f = xlwt.Workbook(encoding = 'utf-8') #设置一个workbook,其编码是utf-8
sheet1 = f.add_sheet(u'阿强的表1', cell_overwrite_ok=True) # 创建sheet
sheet1.write(0, 0, label='epoch') # 将‘列1’作为标题
sheet1.write(0, 1, label='Dice_Loss') # 将‘列1’作为标题
sheet1.write(0, 2, label='G_Loss') # 将‘列2’作为标题
sheet1.write(0, 3, label='D_Loss') # 将‘列3’作为标题
# 将数据写入第 i 行,第 j 列
for j in range(len(datas1)):
sheet1.write(j + 1, 0, epoch[j])
sheet1.write(j + 1, 1, datas1[j])
sheet1.write(j + 1, 2, datas2[j])
sheet1.write(j + 1, 3, datas3[j])
f.save(file_path) # 保存文件
for i in range(1,10+1):
a.append(1)
epo.append(i)
for i in range(1,10+1):
b.append(2)
for i in range(1,10+1):
c.append(3)
data_write("tran_loss.xls",epo, a, b, c)
设置阈值把torch大于或者小于某个值变为1或者0
out = torch.where(out > 0.5, torch.ones_like(out), out)
out = torch.where(out <= 0.5, torch.zeros_like(out), out)
加载模型的权重参数
start_epoch = 0
if os.path.isfile("./models/G_best_7.pth"):
model_param = "./models/G_best_7.pth" # 断点路径
net.load_state_dict(torch.load(model_param)['net']) # 加载模型可学习参数
optimizer.load_state_dict(torch.load(model_param)['optimizer']) # 加载优化器参数
start_epoch = torch.load(model_param)['epoch'] # 设置开始的epoch
for epoch in range(start_epoch + 1, niter+1):
model_pth = {
"net": Net.state_dict(),
'optimizer': optimizer.state_dict(),
"epoch": epoch
}
if not os.path.isdir("./models/"):
os.mkdir("./models/")
torch.save(model_pth, './models/XXXmodel_%s.pth' % (str(epoch)))
路径拼接是斜杆和反斜杠问题
把路径自己不要的格式替换掉就行了
image = image.replace('\\', '/')
随机选取list不重复元素
sample(listA,个数)
求两个list的差集
c = list(set(A)^set(B)) ## 求差集
使用torch.stack注意事项
保存的照片不能去掉通道数,不然保存的话,全部图片都是叠加在一起的,就算了事灰度值图像也必须有个灰度值的通道数1
torch.max用法
X = torch.randn(1, 3, 2, 2)
x = torch.tensor(([[[[ 0.8556, 0.7023],
[-0.2088, -0.2201]],
[[ 2.0535, -1.1469],
[ 1.8301, -1.6326]],
[[-1.0064, -0.4217],
[ 1.9463, 1.3384]]]]))
b = torch.max(x,1)[0]
'''
[[[2.0535, 0.7023],
[1.9463, 1.3384]]]
相当于是把3片的图片,用串串串起来,看哪个大
'''
数组增加维度
im = [3,255,255]
im = np.expand_dims(im , 0)
im = [1,3, 255, 255]
显示3维散点图
ax = plt.subplot(111, projection='3d') # 创建一个三维的绘图工程
# 将数据点分成三部分画,在颜色上有区分度
ax.scatter(i, j, k, c='y') # 绘制数据点
ax.scatter(i, j, k, c='r')
ax.scatter(i, j, k, c='g')
ax.set_zlabel('Z') # 坐标轴
ax.set_ylabel('Y')
ax.set_xlabel('X')
plt.show()
计算网络模型的参数量:
para_total = sum(p.numel() for p in net.parameters() if p.requires_grad)
print('='*10, '参数量为:{:0>4}_{:0>4}'.format(int(para_total/10000),int(para_total%10000)),'='*10)
打印输出:
from datetime import datetime
print('{} Epoch {:<3d}/{:<3d} | Step {:>3d}/{:<3d} | train loss {:.4f}'
.format(datetime.now(), e, args.epochs, j, len(train_loader), loss.item()))
数据格式转换:
c.astype(np.float32)
## 类型有float32、float64、uint8
保存Nii医学图像:
nib.Nifti1Image(imagecrop.squeeze(0).numpy(), a['image_meta_dict']['affine'])\
.to_filename('./pre_label.nii.gz')
显示显卡的信息:
current_device = torch.cuda.current_device()
print("Device:", torch.cuda.get_device_name(current_device))
上采样,放大图像:
## 【放大倍数】
self.upsacle = nn.Upsample(scale_factor=tuple([1,2,2]))
保存图片:
## opencv
import cv2
cv2.imwrite("1.jpg", image)
## 使用PIL
from PIL import Image
im = Image.fromarray(image)
im.save("1.jpg")
## 使用torch格式
import torchvision
img = torch.stack([ x_, y], 0) ## 进行拼接
torchvision.utils.save_image(img .cpu(), 'G:/8.png')
送入transforms时的格式装换
from PIL import Image
PIL_image = Image.fromarray(ndarray_image) #这里ndarray_image为原来的numpy数组类型的输入
最后,老婆压场
喜欢的话,给我老婆点个赞吧☺