记一次CNN模型训练遇到的问题(初训练)

  • csv文件读写

读:

filename = "D:\\桌面文件\\大三上\\大三下\\人工智能\\练习赛数据\\test_data.csv"
df = pd.read_csv(filename)
print(df.info())#简要摘要 information
print(df.head())#输出数据前n行,默认为5
print(df.shape[0])

写:(注意这个方式是一行一行写入,newline=''是为了消除csv文件里的空行)

import csv #调用数据保存文件
import pandas as pd #用于数据输出
with open("D:\\桌面文件\\大三上\\大三下\\人工智能\\练习赛数据\\ans.csv","w",newline='') as csvfile: 
    writer = csv.writer(csvfile)
    writer.writerow(["id","label"])
    t=1
    for i in Ans:
        writer.writerow([t,int(i)])
        t+=1
  • 关于这个tensor转numpy的格式
y.cpu().numpy() ---> y.cpu().detach().numpy()
  •  创建一个空的numpy,取每一行最大的数的下标以及往numpy里添加新的元素
Ans = np.empty(0)
ans = np.argmax(ans,axis=1)
Ans = np.append(Ans,ans)
  • 一个是训练模式,一个是预测模式
net.train()
net.eval()
  • RuntimeError: Expected object of scalar type Long but got scalar type Float for argument #2 'target'

遇到上面类似的错误的解决方法:

loss = criterion(outputs, labels.long())#损失函数

就在labels后面加上.long(),多次报这个错误后发现,它说是什么类型,直接在label后面加上对应的类型即可。

  • Input type (torch.cuda.DoubleTensor) and weight type (torch.cuda.FloatTensor) should be the same

出现上面的错误的时候需要把输入数据的数据类型改一下,模型的数据类型应该不是很好改。

df = df.astype(np.float32)

一般模型为float的数据类型,所以输入的数据类型也要改成float即可。

  • 关于tensor的维度转换
l = inputs.shape[0]
inputs = inputs.view(l,1,80,75)

其实还有很多错误,没有写上来,随手便改了,没有记录。

  • OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"

添加上面两句话即可

  • 随机从一段数里选择一部分数
a=np.arange(0,792)
#8:2 
b=np.random.choice(a,634,replace=False)#训练集下标
c=np.delete(a,b)#验证集下标
torch.save(net, 'MNIST.pkl')
net = torch.load('MNIST.pkl')
  •  dropout调优参数,以及所处的位置

调优参数一般是0.0 p=0.3 p=0.5 有的介绍说p=0.5泛化能力最好,dropout缺点就是训练时间过长

Dropout一般放在全连接层防止过拟合,提高模型返回能力,由于卷积层参数较少,很少有放在卷积层后面的情况,卷积层一般使用batch norm。

 深度学习的loss能否作为衡量模型性能的指标?

结论是:几乎不能!

对于分类问题来说是有一定相关性但几乎不能。

对于一个分类模型来说更关心的是accuracy等指标(还有哪些能够衡量呢?),但是loss并不能直接代表这些指标

 

 

 

 

 

 

 

模型泛化能力差,过拟合

Solution:对模型做正则化,使用dropout技巧or扩大训练集 

欠拟合

Solution:增大模型规模(加深网络层数)甚至换一个更大的模型是有效的优化策略

 

 

模型垃圾,泛化能力差

直接换一个网络

 

  •  ResNet网络遇到的问题
  • pytorch如何修改ResNet等网络的输入通道数?

如果不修改的话输入层和输入的数据不匹配就会报错

net = torchvision.models.resnet18(pretrained=False)
print(net.conv1)
net.conv1 = nn.Conv2d(1, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)

打印网络通道数查看状况,然后直接调用这个Conv2d函数修改网络第一层即可

  • ResNet如果调用Pytorch自带的而不是自己创建的话需要修改输出线性层的个数
resnet18 = models.resnet18()

# 修改全连接层的输出
num_ftrs = resnet18.fc.in_features
resnet18.fc = nn.Linear(num_ftrs, 2)
  • 突然发现pytorch自带许多经典网络,几乎都不需要自己去搭建

torchvision.model中,有很多封装好的模型。

可以分为三类

 

  •  add_module 添加新的层
# 在最后一层添加线性层,使输出的分类类别是10
net.add_module("add_linear", nn.Linear(1000, 10))
# 在classifier最后一层加线性层
net.classifier.add_module("add_linear", nn.Linear(1000, 10))
# 在avgpool后面添加一层BN层
net.avgpool.add_module("add_BN",nn.BatchNorm2d((25088)))

add_moudle里面有两个参数,第一个参数是改层的命名,没有什么限制,其次是添加的层是什么

  •  python里的nan和inf的含义以及解决方法

nan(Not a number)通常是无理数,无法表示的数,而inf是超过浮点表示范围的浮点数(其本质仍是浮点数,但是无穷大)

出现的原因:如果迭代在100轮以内,出现nan,一般情况下是因为你的学习率过高,降低学习率需要;一般来说低于现有学习率1-10倍即可。

出现的根本原因:nan的出现一般是inf-inf,从而得到nan,需要数据归一化,这很重要,梯度爆炸使得学习过程难以继续。loss随着每轮的迭代越来越大,最终超过了浮点数表示范围,就变成了nan。

  •  python数据类型转换

1 单个数据numpy转int,首先numpy.int64和int是完全不一样的!

import numpy as np
#定义一个int变量
a=123
print(type(a)) #<class 'int'>
#强制类型转换为np.int64
b=np.int64(a)
print(type(b)) #<class 'numpy.int64'>
#再强制转化成int
c=int(b)
print(type(c)) #<class 'int'>

强制转换即可

2 多个数据,一个序列数据类型转换 np.astype

arr = arr.astype("float32")
  • python查看数据类型
a=np.array([[1.0,2.0,3.0],[4.0,5.0,6.0]])
print(type(a))
print(isinstance(a,float))
a=a.astype(int)
print(type(a))
print(isinstance(a,int))

输出是

<class 'numpy.ndarray'>
False
<class 'numpy.ndarray'>
False
  • python数组切割操作

hsplit():沿横轴(纵向)拆分原array。可以实现均匀切割或者指定位置切割。(水平切割)

vsplit():沿垂直轴切割原array。同上。(垂直切割)

split():通过参数axis=1或者axis=0(默认axis=0)可以实现水平切割或者垂直切割。split必须要均等分.

array_split():通过参数axis=1或者axis=0可以实现水平切割或者垂直切割。array_split()强制切割,指定切割后的数目实现近似均匀切割。

注意:np.array_split 和np.split(),这两个函数的唯一区别是 split() 必须是等分,否则会抛出异常:ValueError: array split does not result in an equal division。
  • K折交叉验证

它指的是将原始数据随机分成K份,每次选择K-1份作为训练集,剩余的1份作为测试集。交叉验证重复K次,取K次准确率的平均值作为最终模型的评价指标。一般取K=10,即10折交叉验证,如下图所示:

 

 

 

用交叉验证的目的是为了得到可靠稳定的模型。K折交叉验证能够有效提高模型的学习能力,类似于增加了训练样本数量,使得学习的模型更加稳健,鲁棒性更强。选择合适的K值能够有效避免过拟合。

    把10次平均值作为模型泛化能力的评判标准

 

 

 

 

 

 

 

完结撒花!!!

posted @ 2023-03-25 20:09  清风我已逝  阅读(102)  评论(0编辑  收藏  举报