Python+Pytorch学习

        最近又重拾了机器学习的相关技术,在本科毕设的阶段下学习使用了Tensorflow 2.x工具,当时也是不求甚解,直接拿来用了,但现在已经有充足的时间、精力和基础知识来重新学习一下。

        目前机器学习框架有两大方向,Pytorch和Tensorflow 2。对于机器学习的小白的我来说,直观的感受是Tensorflow的框架更加傻瓜式,在这个框架下只需要定义神经网络的结构、输入和输出,然后直接使用其框架下的各种框架函数即可。而对于Pytorch来说,则使用者能操作、定义的细节更多,但与此同时使用难度也会更高。

        通过各种资料也显示,在学术研究范围内,越来越多的人使用Pytorch,其实Tensorflow也不错,但对于普通小白来说入手更快,应用也更快。本着全面发展,多尝试的心态,开始Pytorch学习。       

        小编将从自身的理解习惯开始不断更新这篇博文:

1.Pytorch简介

Pytorch就是一个神经网络框架,使用Pytorch可以跳过很多不必要的底层工作,很多通用的方法、数据结构都已经实现供我们调用,从而可以让我们将精力集中在改进数据质量、网络结构和评估方法上去。

使用和训练神经网络从思考顺序上来说无非就三个阶段:

1)构思神经网络的输入输出和网络结构,其中输入输出非常关键。

2)训练数据集(粗糙的原始数据)

3)如何将训练数据集转换成神经网络能够接受并且能够正确输出的结构。

4)训练神经网络并进行预测。

2.Pytorch定义神经网络的输入、输出和结构

        使用Pytorch定义神经网络非常通用的格式:

class NN(nn.Module):
    def __init__(self):
        super(NN,self).__init__()#继承tOrch中已经写好的类,包含神经网络其余所有通用必要方法函数。
        self.flatten=nn.Flatten()#加入展平函数。
        self.net=nn.Sequential(#调用Sequential方法定义神经网络。
            nn.Linear(100*3,100*3),
            nn.ReLU(),
            nn.Linear(100*3,100*3),
            nn.ReLU(),
            nn.Linear(100*3,27)
        )
    def forward(self,x):#自定义神经网络的前向传播函数,本文使用了正常的前向传播函数,但最终的结果给出三个输出。
        result=self.net(x)
        r1=result[:9]
        r2=result[9:18]
        r3=result[18:27]    
        return [r1,r2,r3]

        到这里基本上已经定义了自己的神经网络了,输入为100*3=200个数据、输出为27个数据。那么问题来了,怎么把数据输入进去呢?

3.Pytorch神经网络的数据格式——tensor

        对于编程小白、机器学习小白的我或者大家来说,tensor的直接定义不好理解。

        tensor表面上只进行了存储,但实际上它包含了很多中方法,直接使用tensor.Method()调用相关方法即可,而省去了自己来定义函数,再操作数据结构。并且在Pytorch进行训练时,也会在其内部调用这些方法,所以就需要我们使用这些数据结构来作为Pytorch神经网的输入,并且神经网络的输出也是tensor形式,numpy array 和 list 和 tensor 的转换其实就是数据相同,但集成了不同方法的数据结构。

        那么下面就是输入数据的定义。train_data和labels都是我们使用python方法写出的list。

#train_data、labels都是list,经过list->ndarray->tensor的转换过程。
train_data=torch.tensor(np.array(train_data)).to(torch.float32).to(device)
labels=torch.tensor(np.array(labels)).to(torch.float32).to(device)

4.使用神经网络进行预测(前向传播)、计算损失函数、反向传播更新梯度

1)进行前向传播

#train_data[0]即为训练数据的第一条输入数据。
prediction=model(train_data[0])

2)计算损失

#定义优化器
optim=torch.optim.SGD(model.parameters(),lr=1e-2,momentum=0.9)
# 定义自己的loss 
loss=(prediction[0]-labels[0]).sum()+(prediction[1]-labels[1]).sum()+(prediction[2]-labels[2]).sum()
#反向传播
optim.zero_grad()#清除上一次的静态梯度,防止累加。
loss.backward()#计算反向传播梯度。
optim.step()#进行一次权值更新。

此处的计算损失和权值依据输入数据更新一次的结果,由此加入一个循环,便可以实现神经网络的训练过程。

3) 训练网络

在正式进入训练网络之前,我们还需要了解一个叫做Batch的东西,如果我们将数据一个一个送进去训练,那么神经网络训练的速度将是十分缓慢的,因此我们每次可以丢进去很多数据让神经网络进行预测,通过计算总体的损失就可以让梯度更快地下降。但训练数据有时又很巨大,所以就需要将整个训练数据打包成一批一批的进入训练,并重复若干次,每训练整个数据一次,会经历若干个batch,这一过程称为一个epoch。

所以为了使网络预测结果更快地收敛,即更快地训练神经网络,我们需要首先对数据进行打包。

import torch.utils.data as Data

bath=50#每批次大小
loader=Data.DataLoader(#制作数据集,只能由cpu读取
    dataset = train_data_set,
    batch_size=bath,#每批次包含数据条数
    shuffle=True,#是否打乱数据
    num_workers=1,#多少个线程搬运数据
)

然后,我们就可以进行神经网络的训练了:

pstep=2#每个多少个批次就输出一次结果
for epoch in range(1000):
    running_loss=0.0
    for step,(inps,labs) in enumerate(loader):
        #取出数据并搬运至GPU进行计算。
        labs=labs.to(device)
        inps=inps.to(device) 
        
        outputs = model(inps)#将数据输入进去并进行前向传播
        loss=loss_fn(outputs,labs)#损失函数的定义
        
        
        optimizer.zero_grad()#清楚上一次的静态梯度,防止累加。
        loss.backward()#反向传播更新梯度
        optimizer.step()#进行一次优化。
        
        running_loss += loss.item()#不加item()会造成内存堆叠
        size=len(labs)*3
        correct=0
        #print("outputs:",outputs.argmax(-1),"\nlabs:",labs.argmax(-1))
        #逐个判断计算准确率
        correct+=(outputs.argmax(-1)==labs.argmax(-1)).type(torch.float).sum().item()
        
        if step % pstep == pstep-1:    # print every 10 mini-batches
            print('[%d, %5d] loss: %.3f correct:%.3f' %
                  (epoch + 1, step + 1, running_loss / pstep,correct/size))
            if correct/size>1:#错误检查
                print("outputs:",outputs.argmax(-1),"\nlabs:",labs.argmax(-1),"\ncorrect:",correct,"\nSize:",size)
            running_loss = 0.0
#保存模型
torch.save(model.state_dict(), "model.pth")
print("Saved PyTorch Model State to model.pth")

5.错误收集

OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.
OMP: Hint This means that multiple copies of the OpenMP runtime have been linked into the program. That is dangerous, since it can degrade performance or cause incorrect results. The best thing to do is to ensure that only a single OpenMP runtime is linked into the process, e.g. by avoiding static linking of the OpenMP runtime in any library. As an unsafe, unsupported, undocumented workaround you can set the environment variable KMP_DUPLICATE_LIB_OK=TRUE to allow the program to continue to execute, but that may cause crashes or silently produce incorrect results. For more information, please see http://www.intel.com/software/products/support/.

如果发生此类错误,重装numpy库就可以。

2023.3.29更新

对近期的pytorch学习进行一些总结:

1.首先是对于pytorch梯度的一些新的理解,当给定的训练数据输入到神经网络中并走完一边后,那么当前网络的梯度实际上是取决于输入的,具体来讲就是当输入确定数据全部在神经网络中走过一遍后,那么当前神经网络的变量是其网络参数,因此我们我们需要对这些变量进行反向传播梯度下降,所以可以得出以下结论:

梯度的产生是输入数据造成的,若没有数据在里面跑完一遍,那么当前神经网络没有梯度,无法进行反向传播梯度更新。

因此我们可以发现一些问题的原因就会得到解决,比如以下这个问题:

Trying to backward through the graph a second time (or directly access saved tensors after they have already been freed). Saved intermediate values of the graph are freed when you call .backward() or autograd.grad(). Specify retain_graph=True if you need to backward through the graph a second time or if you need to access saved tensors after calling backward.

这个问题是我在两个网络共用一个网络时产生的,由于反向传播的时候会使用到当前的梯度并完成梯度清零的操作,当第二个网络再次进行梯度更新的时候就会产生这个现象,尽管当前的网络优化参数的时候并没有涉及当独立的公共网络,当第二个网络回传的时候公共网络的值已经被释放掉了,正确的理解应该是思考数据流过的位置,流过一次位置便产生了梯度,流过一次数据,才能正确的进行梯度优化。

2.训练数据的数据形状shape

对于输入到神经网络中的shape理解,对于shape的理解还是由批训练影响的,pytorch对输入数据的第一个维度都是batch,当我们把数据reshape成(n, data_shape)的时候,那么神经网络就会将这个n理解为batch的数量,特别是一个线性输入进去的时候应当化为(1,data_length)的形状,不然就会被神经网络多个批次从而产生多个输出值,这个问题特别是在对输入没有要求的卷积层显得尤为重要。

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PythonPyTorch是两个不同的东西。Python是一种高级编程语言,而PyTorch是一个基于Python的机器学习框架。PyTorch提供了丰富的工具和函数,用于构建和训练神经网络模型。 在引用\[1\]中的代码示例中,展示了一个简单的训练过程。首先,创建了一个模型对象,并生成了一个随机的向量和标签。然后,定义了一个损失函数和一个优化器。最后,使用优化器对模型进行训练。 在引用\[2\]中的代码示例中,展示了一个模型的前向传播过程。首先,定义了一个输入向量和一个嵌入层。然后,使用嵌入层将输入向量转换为嵌入向量。接下来,使用torch.einsum函数计算输出。最后,返回输出。 在引用\[3\]中的代码示例中,展示了一些与排序和填充相关的操作。首先,定义了一个张量a和一个长度向量lengths。然后,使用torch.sort函数对lengths进行排序,并获取排序后的长度和索引。接下来,根据索引对张量a进行排序。然后,定义了一个嵌入层和一个LSTM层,并将张量a输入到嵌入层中。接下来,使用pack_padded_sequence函数对输入进行填充。然后,使用LSTM层对填充后的输入进行处理。最后,使用pad_packed_sequence函数对输出进行填充,并根据索引对输出进行排序。 总之,Python是一种编程语言,而PyTorch是一个用于机器学习的框架。在PyTorch中,可以使用Python编写代码来构建和训练神经网络模型,并进行各种操作,如排序和填充。 #### 引用[.reference_title] - *1* *2* *3* [python+pytorch学习点滴记录](https://blog.csdn.net/benben044/article/details/123881062)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值