pytorch_神经网络构建1

news2024/12/25 1:24:09

文章目录

    • pytorch简介
    • 神经网络基础
    • 分类问题分析:逻辑回归模型
    • 逻辑回归实现
    • 多层神经网络
    • 多层网络搭建
    • 保存模型

pytorch简介

为什么神经网络要自定义数据类型torch.tensor?
tensor可以放在gpu上训练,支持自动求导,方便快速训练,同时支持numpy的运算,是加强版,numpy不支持这些
为什么要求导?
导数是真实值和预测值的误差函数下降最快的地方,根据求导可以快速降低误差值,让真实值和预测值贴合
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

神经网络基础

监督学习:已经打标记的样本进行训练,然后预测
非监督学习:对一些无标记数据进行结构化分类,发现潜在的规律
强化学习:一个机器不断根据新的输入做出决策,然后根据结果进行奖惩来学习
线性模型:y=wx+b,w就是要优化的值,我们要根据损失值来不断优化w让他的预测贴近真实值
这需要知道loss函数,(真实值和预测值之间的误差),然后根据loss函数的反馈优化w降低loss
当loss求和最小的时候可以得出预测越来越准
为了减少loss就需要知道loss在哪个方向下降的最快,这就是求导,梯度下降算法
在这里插入图片描述
更直观一点是让loss下降的更快,以至于降到最低,让真实值和预测值无限贴合,
学习率代表了斜率变化的步长,合理的设置会方便于我们找到最优w,错误的设置过大过小会导致预测值无法贴合真实值
在三维和多维度图象上更容易理解这一点
在这里插入图片描述
当有三个维度的数据时更加直观
在这里插入图片描述
那么构建模型流程如下
定义参数,定义损失函数,定义网络模型,这里为线性模型,然后根据损失函数优化参数w让线性模型拟合的更好
理解线性模型对未来的深层模型构建有很大帮助
我们定义一些点,然后用线性模型拟合这些数据

x_train	np.array([[3.3],[4.4],[5.5],[6.71],[6.93],[4.168],[9.779],[6.182],[7.59],[2.167],[7.042],[10.791],[5.313],[7.997],[3.1]],dtype=np.float32)
y_train	=np.array([[1.7],[2.76],[2.09],[3.19],[1.694],[1.573],[3.366],[2.596],[2.53],[1.221],[2.827],[3.465],[1.65],[2.904],[1.3]],dtype=np.float32)

在这里插入图片描述
然后将这些数据转化为tensor类型,定义参数wb,使用正态分布随机初始化数据wb,定义网络模型,损失函数模型
损失函数模型计算误差方式为求平方差之和

x_train	=torch.from_numpy(x_train)
y_train	=torch.from_numpy(y_train)
w1=Variable(torch.randn(1),requires_grad=True)
b1=Variable(torch.zeros(1),requires_grad=True)
def linear_model(x):
    return x*w1+b1
def get_loss(y_,y):
    return torch.mean((y_-y_train)**2)
y_=linear_model(x_train)
loss=get_loss(y_,y_train)

画出初始化后的预测图形为:这肯定不对的,然后对其进行优化

plt.plot(x_train.data.numpy(), y_train.data.numpy(), 'bo', label='real')
plt.plot(x_train.data.numpy(), y_.data.numpy(), 'ro', label='estimated')
plt.legend()

在这里插入图片描述
进行10次迭代
获得预测值,计算误差,将之前的梯度归零,计算新的梯度,根据新的梯度对参数wb进行优化

for e in range(10): # 进行 10 次更新
    y_ = linear_model(x_train)
    loss = get_loss(y_, y_train)
    
    w.grad.zero_() # 记得归零梯度
    b.grad.zero_() # 记得归零梯度
    loss.backward()
    
    w.data = w.data - 1e-2 * w.grad.data # 更新 w
    b.data = b.data - 1e-2 * b.grad.data # 更新 b 
    print('epoch: {}, loss: {}'.format(e, loss.data[0]))

在这里插入图片描述
使用的是科学计数法,1e相当于10,科学记数法以x*10^n将所有数据进行分解,1e-2就是10的负二次方.0.01
梯度归零的意义在于得到新的梯度前清空上一次计算的梯度,对新的梯度进行优化
然而实际上,参数点往往分布的并不规律,也不可能仅仅用wx+b就可以拟合,
我们来设计一个新的图像
y = x+x2+x3+b

# 画出这个函数的曲线
x_sample = np.arange(-3, 3.1, 0.1)
y_sample = b_target[0] + w_target[0] * x_sample + w_target[1] * x_sample ** 2 + w_target[2] * x_sample ** 3
plt.plot(x_sample, y_sample, label='real curve')
plt.legend()

在这里插入图片描述
然后设置一些训练数据x和y
x为一个多行3列矩阵

x_train = np.stack([x_sample ** i for i in range(1, 4)], axis=1)
x_train = torch.from_numpy(x_train).float() # 转换成 float tensor
y_train = torch.from_numpy(y_sample).float().unsqueeze(1) # 转化成 float tensor 

定义wb参数和神经网络模型,这里依旧为线性模型,损失函数,损失函数同wx+b模型依旧求平常差之和

# 定义参数和模型
w = Variable(torch.randn(3, 1), requires_grad=True)
b = Variable(torch.zeros(1), requires_grad=True)
# 将 x 和 y 转换成 Variable
x_train = Variable(x_train)
y_train = Variable(y_train)
def multi_linear(x):
    return torch.mm(x, w) + b

查看原始拟合图像
在这里插入图片描述

更新参数wb

# 进行 100 次参数更新
for e in range(100):
    y_pred = multi_linear(x_train)
    loss = get_loss(y_pred, y_train)
    w.grad.data.zero_()
    b.grad.data.zero_()
    loss.backward()
    w.data = w.data - 0.001 * w.grad.data
    b.data = b.data - 0.001 * b.grad.data
# 画出更新之后的结果
y_pred = multi_linear(x_train)

plt.plot(x_train.data.numpy()[:, 0], y_pred.data.numpy(), label='fitting curve', color='r')
plt.plot(x_train.data.numpy()[:, 0], y_sample, label='real curve', color='b')
plt.legend()

画出拟合后的图形

在这里插入图片描述

w	=	Variable(torch.randn(3,	1),	requires_grad=True)

设置自变张量不可缺少
varable在pytorch0.4之后就不再使用,以后的torch自带梯度计算
上面是单w权重的情况,实际使用中往往是多权重,会有w1,2,3
但是写法不变

plt.plot(x_train.data.numpy()[:,	0],	y_pred.data.numpy(),	label='fitting	curve',
color='r')

x_train.data.numpy()[:, 0]代表x_train所有行的第一个值x值
可以看到,对于线性模型只要模型设置正确,loss函数设置合理,就能够得到贴近值,这对于线性模型求解益处巨大,
然而有一类问题是线性问题不涉及的,那就是离散问题,无法用公式描述

分类问题分析:逻辑回归模型

他和上面的模型的区别在于多了一个sigmod函数,分类函数
在这里插入图片描述
所有的y值都能够被放在-1到1的区间,这意味着可以把它看做概率,
分类问题和回归问题的区别在于回归问题是连续问题,比如拟合曲线,分类是离散问题,在解决问题前需要明白要解决的是那种问题

loss函数的变化:
既然是分类,输入任意数据经过sigmoid,a类概率为y_,b类概率为1-y_,如果输入的数据类型为a,则y_越大越好,1-y_越小越好
y_是概率值<=1
loss=-(y*log(y_)+(1-y)*log(1-y_))
输入的y只能为0,1
当输入0,0的概率损失函数loss=-(log(1-y_)).表示预测为假越大越好
当输入1,1的概率损失函数为loss=-(log(y_)),表示预测为真越大越好
当然log是有底数的,它的底数是e

逻辑回归实现

我们观察这些点的分布

# 从 data.txt 中读入点
with open('./data.txt', 'r') as f:
    data_list = [i.split('\n')[0].split(',') for i in f.readlines()]
    data = [(float(i[0]), float(i[1]), float(i[2])) for i in data_list]

# 标准化
x0_max = max([i[0] for i in data])
x1_max = max([i[1] for i in data])
data = [(i[0]/x0_max, i[1]/x1_max, i[2]) for i in data]

x0 = list(filter(lambda x: x[-1] == 0.0, data)) # 选择第一类的点
x1 = list(filter(lambda x: x[-1] == 1.0, data)) # 选择第二类的点

plot_x0 = [i[0] for i in x0]
plot_y0 = [i[1] for i in x0]
plot_x1 = [i[0] for i in x1]
plot_y1 = [i[1] for i in x1]

plt.plot(plot_x0, plot_y0, 'ro', label='x_0')
plt.plot(plot_x1, plot_y1, 'bo', label='x_1')
plt.legend(loc='best')

在这里插入图片描述
分布离散问题,使用逻辑回归来进行分类较为合适

torch.manual_seed(2000)

随机数种子,用于初始化模型参数,划分数据集,打乱数据等,有了初始值,则可以确保不同机器上,不同执行次数上模型初始化,数据初始化一致,实验结果具备可重复性

x0=list(filter(lambda x:x[-1] ==0.0,data))

filter传入一个lambda表达式,可迭代对象,返回一个迭代器,list将迭代器转化为list对象
对data中的行x进行迭代,找到每行最后元素等于0.0的行

plt.plot(plot_x1,plot_y1,"bo",label="x_1")

在坐标轴上画图,参数分别为x,y,颜色,标签
颜色ro红色,bo蓝色

plt.legend(loc='best')

选择最佳位置放置图像
那么延续之前线性模型的经验,我们需要设置wb,设置损失函数(这里不再求平方差而是求log),神经网络模型
对于sigmoid函数,
pytroch已经内置了这个函数,而且实现的速度更快,底层用c++编写,同时还有其他函数,直接调用即可
因此初始化wb和loss函数

np_data = np.array(data, dtype='float32') # 转换成 numpy array
x_data = torch.from_numpy(np_data[:, 0:2]) #  转换成 Tensor,大小是 [100, 2]
y_data = torch.from_numpy(np_data[:, -1]).unsqueeze(1) # 转换成 Tensor,大小是 [100, 1]
w = Variable(torch.randn(2, 1), requires_grad=True) 
b = Variable(torch.zeros(1), requires_grad=True)
def sigmoid(x):
    return 1 / (1 + np.exp(-x))
def binary_loss(y_pred, y):
    logits = (y * y_pred.clamp(1e-12).log() + (1 - y) * (1 - y_pred).clamp(1e-12).log()).mean()
    return -logits
def logistic_regression(x):
    return F.sigmoid(torch.mm(x, w) + b)

将图像绘画出来如下

# 画出参数更新之前的结果
w0 = w[0].data[0]
w1 = w[1].data[0]
b0 = b.data[0]

plot_x = np.arange(0.2, 1, 0.01)
plot_y = (-w0 * plot_x - b0) / w1

plt.plot(plot_x, plot_y, 'g', label='cutting line')
plt.plot(plot_x0, plot_y0, 'ro', label='x_0')
plt.plot(plot_x1, plot_y1, 'bo', label='x_1')
plt.legend(loc='best')

在这里插入图片描述
那么毫无疑问的,对于每一个坐标点[x,y]的分类是错误的,这里我们设置w的参数为2,生成两个w为xy加权重
但同时每次都手动更新一批wb是不合适的,应该做到w一次设置,自动更新,我们只关心w的数量和步长,手动调整w
变化不是我们应该关心的,我们需要一个w自动优化器

torch.optim接受一个nn.Parameter所定义的数据类型,然后自动对其中的所有数据进行更新维护
nn.Parameter默认带梯度,而Variable默认不带梯度
如果只是遍历更新参数似乎也并无必要,实际上optim带有众多参数优化器,比如SGD梯度下降方法来更新参数
这里设置学习率为1
以后更新参数只需要两行代码,不涉及具体参数操作

w=nn.Parameter(torch.randn(2,1))
b=nn.Parameter(torch.zeros(1))
optimizer=torch.optim.SGD([w,b],lr=1.)
for e in range(1000):
    # 前向传播
    y_pred = logistic_regression(x_data)
    loss = binary_loss(y_pred, y_data) # 计算 loss
    # 反向传播
    optimizer.zero_grad() # 使用优化器将梯度归 0
    loss.backward()
    optimizer.step() # 使用优化器来更新参数
    # 计算正确率
    mask = y_pred.ge(0.5).float()
    acc = (mask == y_data).sum().data[0] / y_data.shape[0]
    if (e + 1) % 200 == 0:
        print('epoch: {}, Loss: {:.5f}, Acc: {:.5f}'.format(e+1, loss.data[0], acc))

画出新分类图
在这里插入图片描述
其实不仅仅w参数有优化器,对于loss函数也有优化器,这意味着对于常见的分类可以直接使用预设的优化器,而不用自己来实现,而且预设的优化器底层用c++实现,相比于我们自己写的效率更高
线性回归里,上一次使用的计算平方差的优化器函数为nn.MSE()
而逻辑回归里使用的二分类优化器函数为nn.BCEWithLogitsLoss(),这个损失函数优化器还集成了sigmoid,那么之前在计算真实值与推测值矩阵计算之后再进行的sigmoid得到概率操作就不用做了,直接调用这个函数输入预测值和真实值,得到的就是预测概率的损失值的和的平均值(原来的功能,都一样,更快而已)
得到loss优化器对象,计算损失值,在大型网络中预设的loss运行速度更为明显

# 使用自带的loss
criterion = nn.BCEWithLogitsLoss() # 将 sigmoid 和 loss 写在一层,有更快的速度、更好的稳定性
w = nn.Parameter(torch.randn(2, 1))
b = nn.Parameter(torch.zeros(1))
def logistic_reg(x):
    return torch.mm(x, w) + b
optimizer = torch.optim.SGD([w, b], 1.)
for e in range(1000):
    # 前向传播
    y_pred = logistic_reg(x_data)
    loss = criterion(y_pred, y_data)
    # 反向传播
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    # 计算正确率
    mask = y_pred.ge(0.5).float()
    acc = (mask == y_data).sum().data[0] / y_data.shape[0]
    if (e + 1) % 200 == 0:
        print('epoch: {}, Loss: {:.5f}, Acc: {:.5f}'.format(e+1, loss.item(), acc))

一些补充:

  1. 当jupyter出现问题时重启一下也许就可以 代码过了保质期变得不可信任,文件不能加载,重新信任一下
    为什么要将numpy数据转化为torch数据
    因为torch数据被优化了,可以放在gpu上训练,支持自动求导,非常适合矩阵运算
    同时不要混淆list和numpy区别,list是python提供的可变列表,支持多种元素
    而numpy则长度不可变,只支持同类型元素,但同时速度更快,结构更加紧凑,提供了多种操作函数
    往往是先将list转化为numpy然后再转为torch
    这里设定了numpy每个元素为float32类型,代表所有numpy的所有行的前两个元素形成的列表被转化为torch格式
np_data=np.array(data,dtype='float32')
x_data=torch.form_numpy(np_data[:,0:2])

同时对于目标数据,需要将其排成一列

y_data=torch.from_numpy(np.data[:,-1]).unsqueeze(1)

clamp是一个判断语句,如果y_pred 或者1-y_pred小于这个数值就设置为这个数值
因为log的x区间不能小于等于0
逻辑回归函数调用sigmoid来对矩阵运算的结果进行分类,得到分类概率列表
loss求解损失函数中,会计算出预测值和真实值之间的log,并对输入的x矩阵所有数据的log差求和求平均值mean

ge(0.5)是一个比较器,低于此值归零,高于此值归1,用于分类,返回值与原数据类型相同
(mask==y_data).sum()统计两个torch对象有多少相等的,t这是orch对象的函数,作为神经网络的数据元素,它具备众多函数方法为了神经网络服务

多层神经网络

之前的线性回归模型和逻辑回归模型,因为都涉及到一层w的运算,都被视作单层神经网络
无非是不断优化一层w的值到合适位置而已

事实上,复杂而有效的神经网络是深层的,往往波浪式的w向前传递,同时模拟人脑神经元激活阈值的原理,提出了激活函数
sigmoid
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
越来越多的实践表明relu的优化效果更好,一层网络是max(0,wx+b),二层就是w2max(0,w1x+b1)+b2
那么为什么需要激活函数呢?
本质上讲激活函数让神经网络有了深层的可能,通过改变w使得网络可以拟合成各种情况
如果不使用激活函数来改变网络形状,那么最后就会变成
w1
x w2(w1x) w3(w2(w1x) ) w1w2w3…x Wnx 归根究底还是单层神经网络

多层网络搭建

解决多分类问题
在这里插入图片描述
画出分类图形函数::

def plot_decision_boundary(model, x, y):
    # Set min and max values and give it some padding
    x_min, x_max = x[:, 0].min() - 1, x[:, 0].max() + 1
    y_min, y_max = x[:, 1].min() - 1, x[:, 1].max() + 1
    h = 0.01
    # Generate a grid of points with distance h between them
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    # Predict the function value for the whole grid
    Z = model(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    # Plot the contour and training examples
    plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.ylabel('x2')
    plt.xlabel('x1')
    plt.scatter(x[:, 0], x[:, 1], c=y.reshape(-1), s=40, cmap=plt.cm.Spectral)

传入模型和数据,即可对数据进行可视化分类

xx,yy=np.meshgrid(np.arange(x_min,x_max,h),np.arange(y_min,y_max,h))

meshgrid传入两个一维数组,生成两个二维数组,xx的shape为(y_max-y_min,x_max-x_min)
yy的shape为(x_max-x_min,y_max-y_min),这个很好理解,可以看做画了一个坐标网格,xx和yy为每一个点都设定了坐标
在这里插入图片描述

z=model(np.c_[xx.ravel(),yy.ravel()])

将xx和yy一维展开,然后由np.c_得到它们所标记的每一个点,每个点交给模型,让模型算出新的目标numpy数组,然后让其形状大小和xx相同,这样方便展开绘画
在这里插入图片描述

plt.contourf(xx,yy,z,cmap=plt.cm.Spectral)

xx和yy绘制网格,z来画出分割点,cmap来设定颜色,设定为渐变色,从高到低由红绿蓝渐变方便查看

plt.scatter(x[:,0],x[:,1],c=y.reshape(-1),s=40,cmap=plt.cm.Spectral)

根据坐标绘制散点图,参数为x,y坐标,c函数值,散点大小,颜色渐变

那么要分类的图形是怎样的?可以画出一个图

我们要画的是一个复杂的花色图像,红蓝相间,由sin和cos函数组合而成
构思逻辑如下:
指定某个范围的数据生成sin和cos的x坐标值列表
然后根据这些坐标值生成新的坐标y值,即sin,cos值
通过公式[sin(x)*sin(x),sin(x)*cos(x)]来说生成每一组xy的坐标点来进行绘图
然后绘制这些坐标即可

allPoint=400
halfCategory=int(allPoint/2)
xy=np.zeros((allPoint,2))#存储x和y值的坐标矩阵,数据矩阵,400行,2列
y=np.zeros((allPoint,1))#存储y值的坐标矩阵,分类目标矩阵,400行
for i in range(2):#可视化视图
    ix=range(i*halfCategory,(i+1)*halfCategory)#对xy坐标进行圈定范围
    t=np.linspace(i*3.12,(i+1)*3.12,halfCategory)#生成sin,cos演化周期的x值
    x=30*np.sin(8*t)#生成sinx值,用于生成花型图案的基础y矩阵
    xy[ix]=np.c_[x*np.sin(t),x*np.cos(t)]#构建一个二维矩阵,有两个特殊的一维矩阵构成,将这两个一维矩阵组合生成xy坐标矩阵,放入xy中
    y[ix]=i#构建坐标值矩阵
plt.scatter(xy[:,0],xy[:,1],c=y.reshape(-1),s=40,cmap=plt.cm.Spectral)

在这里插入图片描述

那么红蓝分类的点就当作原始数据,y值目标值当做分类数据,这样xy和y数据矩阵就构建好了
那么接下来我们使用逻辑回归一层分类,二层网络,三层网络分别进行实验分类效果
构建训练参数x,y
初始化wb,设置参数优化器和loss优化器
循环100次优化wb,再次绘图

x_trainData=torch.from_numpy(np.array(xy)).float()
y_trainData=torch.from_numpy(np.array(y)).float()
w=nn.Parameter(torch.randn(2,1))
b=nn.Parameter(torch.randn(1))
def logistic_regression(x):
    return torch.mm(x,w)+b
optimizer=torch.optim.SGD([w,b],1e-1)
lossor=nn.BCEWithLogitsLoss()
for i in range(100):
    y_pred=logistic_regression(x_trainData)
    loss=lossor(y_pred,y_trainData)
    optimizer.zero_grad()
    optimizer.step()

将参数进行新绘图

def plot_logistic(x):
    x = Variable(torch.from_numpy(x).float())
    out = F.sigmoid(logistic_regression(x))
    out =out.ge(0.5).float()
    return out.data.numpy()
plot_decision_boundary(lambda x_trainData: plot_logistic(x_trainData), x_trainData.data.numpy(), y_trainData.data.numpy())
plt.title('logistic regression')

在这里插入图片描述
效果并不理想,只能进行简单的二分类
我们构建一个两层图像,并使用tanh作为激活函数,再次看效果
第一层网4个神经元,经过它之后原有的数据被扩容了4倍,如果熟悉矩阵运算,假设原数据为x[100,2],经过w[2,4],就会变成[100,4],然后经过激活函数剪枝,激活部分有用的神经元,最后由一个神经元输出01分类数据
矩阵乘法就是,由mxn的矩阵与nxz的矩阵相乘,得到mxz的新矩阵,其中新矩阵的每一个数值都是由行列坐标ij计算,行对应m的行,列对应z的列,对应值相乘的和为新矩阵的值
比如
在这里插入图片描述

w1=nn.Parameter(torch.randn(2,4))
b1=nn.Parameter(torch.randn(4))
w2=nn.Parameter(torch.randn(4,1))
b2=nn.Parameter(torch.randn(1))
# 定义模型
def two_network(x):
    x1 = torch.mm(x, w1) + b1
    x1 = F.tanh(x1) # 使用 PyTorch 自带的 tanh 激活函数
    x2 = torch.mm(x1, w2) + b2
    return x2
optimizer=torch.optim.SGD([w1,b1,w2,b2],1.)
for i in range(1000):
    y_pred=two_network(x_trainData)
    loss=lossor(y_pred,y_trainData)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    if i%200==0:
        print(loss.item())

分类效果并不好,但相比于逻辑回归有了改善
在这里插入图片描述
如果想要取得更好的效果,我们可以增加训练神经元的次数和深度,然而需要注意的是神经元的次数优势并不会带来更好的训练效果,因为参数优化有极限的,但是深度结构的改变会带来质的飞跃
我们可以尝试增加多个神经元来模拟分类效果,但是在一些大型项目中这样的神经元可能有几百亿个,逐个设置参数是不合理的,因此提供了参数初始化工具,在设置网络层数的同时将网络结构一并设计,这样我们只需要关注网络的参数和层数如何设计而不用做重复劳动
一个是Sequential,一个是 Module
会得到一个神经网络模型,同时设置了每层神经元的数量和网络结构

seq_net=nn.Sequential(
nn.Linear(2, 10),
nn.Tanh(),
nn.Linear(10, 8),
nn.Tanh(),
nn.Linear(8, 5),
nn.Tanh(),
nn.Linear(5, 1)
)

和单层设计一样,我们可以随意的查看每层的结构和权重参数

seq_net[0]
#Linear(in_features=2, out_features=10, bias=True)
w1=seq_net[0].weight

接下来只需要设置参数优化器,loss优化器,将数据导入seq_net就能够执行训练了,lossor之前已经进行过定义,就是nn.BCEWithlogitsloss()

param=seq_net.parameters()
paramOptimizer=torch.optim.SGD(param,1.)
for i in range(20000):
    y_pred=seq_net(x_trainData)
    loss=lossor(y_pred,y_trainData)
    paramOptimizer.zero_grad()
    loss.backward()
    paramOptimizer.step()

查看多层网络的分类效果
在这里插入图片描述
当然对于网络结构还有更好的写法,使用modul定义模型更符合语法规范
模板为:
可以设计网络结构,然后设置前向传播如何构建,就像一个类调用
Module 里面也可以使用 Sequential

class 网络名字(nn.Module):
    def __init__(self, 一些定义的参数):
        super(网络名字, self).__init__()
        self.layer1 = nn.Linear(num_input, num_hidden)
        self.layer2 = nn.Sequential(...)
        ...

        定义需要用的网络层

    def forward(self, x): # 定义前向传播
        x1 = self.layer1(x)
        x2 = self.layer2(x)
        x = x1 + x2
        ...
        return x

如下设计一个三层网络,查看权重和网络层结构就像类调用一样

class modelNet(nn.Module):
    def __init__(self,inputLayer,hiddenLayer,outputLayer):
        super(modelNet,self).__init__()
        self.layer1=nn.Linear(inputLayer,hiddenLayer)
        self.layer2=nn.Tanh()
        self.layer3=nn.Linear(hiddenLayer,outputLayer)
    def forward(self,x):
        x=self.layer1(x)
        x=self.layer2(x)
        x=self.layer3(x)
        return x
mNet=modelNet(2,4,1)
mNet.layer1.weight

对其进行训练

mParamOptimizer=torch.optim.SGD(mNet.parameters(),1.)
for i in range(20000):
    y_pred=mNet(x_trainData)
    loss=lossor(y_pred,y)
    mParamOptimizer.zero_grad()
    loss.backward()
    mParamOptimizer.step()

保存模型

1,将网络结构和参数一起保存
前面是网络模型,后面是路径

torch.save(seq_net, 'save_seq_net.pth')

读取模型和参数,得到新的神经网络对象

seq_net1 = torch.load('save_seq_net.pth')

2,只保存参数

# 保存模型参数
torch.save(seq_net.state_dict(), 'save_seq_net_params.pth')

已经有网络结构了,只需要加载预设参数
得到新的神经网络

seq_net2.load_state_dict(torch.load('save_seq_net_params.pth'))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1059546.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++项目:【高并发内存池】

文章目录 一、项目介绍 二、什么是内存池 1.池化技术 2.内存池 3.内存池主要解决的问题 4.malloc 三、定长的内存池 四、高并发内存池整体框架设计 1.高并发内存池--thread cache 1.1申请内存&#xff1a; 1.2释放内存&#xff1a; 1.3用TLS实现thread cache无锁访…

GD32F10 串口通信

1. 什么是通信 通信&#xff0c;指人与人或人与自然之间通过某种行为或媒介进行的信息交流与传递&#xff0c;从广义上指需要信息的双方或多方在不违背各自意愿的情况下采用任意方法&#xff0c;任意媒质&#xff0c;将信息从某方准确安全地传送到另方。通信双方如果想正确传输…

SystemUI导航栏

SystemUI导航栏 1、系统中参数项1.1 相关开关属性2.2 属性设置代码 2、设置中设置“三按钮”导航更新流程2.1 属性资源覆盖叠加2.2 SystemUI导航栏接收改变广播2.3 SystemUI导航栏布局更新2.4 时序图 android13-release 1、系统中参数项 1.1 相关开关属性 设置->系统->…

C++算法 —— 动态规划(9)完全背包问题

文章目录 1、动规思路简介2、完全背包【模板】3、零钱兑换4、零钱兑换Ⅱ5、完全平方数 背包问题需要读者先明白动态规划是什么&#xff0c;理解动规的思路&#xff0c;并不能给刚接触动规的人学习。所以最好是看了之前的动规博客&#xff0c;以及01背包博客&#xff0c;才能看完…

学习C++语言可以适用于哪些方面

学习C可以让你具备开发各种类型软件和系统的能力&#xff0c;它是一种通用的、高性能的编程语言。以下是学习C的一些用途和应用领域&#xff1a; 系统开发&#xff1a;C被广泛用于操作系统、驱动程序和嵌入式系统的开发。通过学习C&#xff0c;你可以编写底层的系统代码&#x…

java大富翁

一、 概述 Java Swing大富翁游戏是一个经典的大富翁桌面游戏的简单实现&#xff0c;使用Java Swing库创建。该游戏允许玩家在一个虚拟棋盘上掷骰子&#xff0c;购买和升级属性&#xff0c;赚取租金和尽量丰富自己。这个文档说明将介绍如何安装和运行游戏&#xff0c;以及游戏规…

【C++】C++11——右值引用和移动语义、左值引用和右值引用、右值引用使用场景和意义、完美转发、新的类功能

文章目录 C115.右值引用和移动语义5.1左值引用和右值引用5.2左值引用与右值引用比较5.3右值引用使用场景和意义5.4右值引用引用左值及其一些更深入的使用场景分析5.5完美转发 6.新的类功能 C11 5.右值引用和移动语义 右值引用是C11引入的一个新特性&#xff0c;用于支持移动语义…

冯诺依曼体系结构与进程的初步理解

目录 一&#xff0c;冯诺依曼体系结构 1.是什么&#xff1f;特点 2.为什么&#xff1f; 二&#xff0c;操作系统 三&#xff0c;进程 1.什么是进程&#xff1f; 2.查看进程 3.进程的管理 4.fork()创建子进程 1.fork()简介 2.fork()干了啥 3.fork()为什么会有两个返回…

【Java】微服务——Ribbon负载均衡(跟进源码分析原理)

添加LoadBalanced注解&#xff0c;即可实现负载均衡功能&#xff0c;这是什么原理 1.负载均衡原理 SpringCloud底层其实是利用了一个名为Ribbon的组件&#xff0c;来实现负载均衡功能的。 2.源码跟踪 为什么我们只输入了service名称就可以访问了呢&#xff1f;之前还要获取…

mstsc无法保存RDP凭据, 100%生效

问题 即使如下两项都打勾&#xff0c;其还是无法保存凭据&#xff0c;特别是连接Ubuntu (freerdp server)&#xff1a; 解决方法 网上多种复杂方法&#xff0c;不生效&#xff0c;其思路是修改后台配置&#xff0c;以使mstsc跟平常一样自动记住凭据。最后&#xff0c;如下的…

Python无废话-办公自动化Excel写入操作

Python 办公自动化-Excel写入 创建并保存Excel文件 import openpyxl workbookopenpyxl.Workbook() #创建空Excel文件 sheetworkbook.active #获取活动的工作表 sheet.title“测试“ #修改sheet工作表名称为测试 workbook.save(“data\input\Test.xlsx”) #保存Excel文件 …

R中的min()函数 和max()函数

通过min()函数和max()函数产生Inf 数值空集的最小值和最大值是Inf和–Inf(按此顺序&#xff01;)这确保了传递性&#xff0c;例如min(x1&#xff0c;min(x2)) min(x1&#xff0c;x2)。对于数值x&#xff0c;每当length (x) 0时&#xff0c;max(x) - Inf和min(x) Inf(如果需…

C#餐饮收银系统

一、引言 餐饮收银系统是一种用于管理餐馆、咖啡厅、快餐店等餐饮业务的计算机化工具。它旨在简化点餐、结账、库存管理等任务&#xff0c;提高运营效率&#xff0c;增强客户体验&#xff0c;同时提供准确的财务记录。C# 餐饮收银系统是一种使用C#编程语言开发的餐饮业务管理软…

SDK Vitis记录

文章目录 SDK记录SDK中报错“undefined reference to sqrt”的解决方法通过XML文件导入工程的include路径方法说明 其他设置编译选项设置某些文件/文件夹不编译单独设置文件的编译选项 向存储区中导入/导出数据通过GUI操作使用命令行操作 产生C代码的MAP文件在Xilinx SDK 工程的…

Golang 中的调试技巧

掌握有效的策略和工具&#xff0c;实现顺畅的开发 调试是每位开发人员都必须掌握的关键技能。它是识别、隔离和解决代码库中问题的过程。在 Golang 的世界中&#xff0c;掌握有效的调试技巧可以显著提升您的开发工作流程&#xff0c;并帮助您创建更可靠和健壮的应用程序。在本…

C语言 —— 函数栈帧的创建和销毁

在我们之前学习函数的时候&#xff0c;我们可能有很多困惑? 比如: 局部变量是怎么创建的?为什么局部变量的值是随机值?函数是怎么传参的?传参的顺序是怎样的?形参和实参是什么关系?函数调用是怎么做的?函数调用是结束后怎么返回的? 那么要解决这些问题, 我们就需要知道…

Raspberry Pi 5 新平台 新芯片组

Raspberry Pi 5 的 CPU 和 GPU 性能提高了两到三倍&#xff1b;内存和 I/O 带宽大约是两倍&#xff1b;并且是首款采用英国剑桥内部设计的芯片的 Raspberry Pi 计算机&#xff0c;4GB 型号的售价为 60 美元&#xff0c;8GB 版本的售价为 80 美元 主要特点包括&#xff1a; 2.4…

Zama的fhEVM:基于全同态加密实现的隐私智能合约

1. 引言 Zama的fhEVM定位为&#xff1a; 基于全同态加密实现的隐私智能合约 解决方案 开源代码见&#xff1a; https://github.com/zama-ai/fhevm&#xff08;TypeScript Solidity&#xff09; Zama的fhEVM协议中主要包含&#xff1a; https://github.com/zama-ai/tfhe-…

Windows11+VS2022+OCCT7.6.0安装配置记录

Windows11VS2022OCCT7.6.0安装配置记录 工具及源码准备VS2022以及CMake下载OCCT源码下载第三方库 CMake修改occt_toolkit.cmake进行CMake Visual Studio环境配置配置包含目录配置库目录配置链接器设置系统环境变量配置项目调试环境环境测试 其他方法 主要参考此文&#xff0c;在…

自然语言处理的分类

动动发财的小手&#xff0c;点个赞吧&#xff01; 简介 作为理解、生成和处理自然语言文本的有效方法&#xff0c;自然语言处理&#xff08;NLP&#xff09;的研究近年来呈现出快速传播和广泛采用。鉴于 NLP 的快速发展&#xff0c;获得该领域的概述并对其进行维护是很困难的。…