【私人笔记】:pytorch + python 的一些用法

实现进度条效果,不在是每次更新则是输出一条信息提示:、

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关系图:

CUDA 12.1 Update 1 Release Notes

https://blog.csdn.net/qq_37217876/article/details/113199937

Previous PyTorch Versions | PyTorch

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安装

安装老版本的Pytorch - 腾讯云开发者社区-腾讯云

# 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

[Anaconda] 安装cuda9.2版本的pytorch_让我安静会的博客-CSDN博客

安装指定库

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 GPU版本安装教程,非常详细,建议收藏-CSDN博客

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=P = \frac{F-1}{2},其中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 

 图从左到右为:源图,<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数组类型的输入

最后,老婆压场

喜欢的话,给我老婆点个赞吧☺

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值