ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Pytorch搭建神经网络实现房价预测:手把手教你用Pytorch搭建神经网络,然后用起来

2026/9/13 23:14:14 拓冰建站 浏览量
Pytorch搭建神经网络实现房价预测:手把手教你用Pytorch搭建神经网络,然后用起来 手把手教你用Pytorch搭建神经网络然后用起来前言1 Pytoch搭建神经网络的方式2 神经网络的设计原则3 训练一个能够预测房价的神经网络3.1 数据准备3.2 神经网络设计3.3 训练网络3.4 模型的评估3.5 模型的使用总结前言教你如何使用Pytorch框架搭建自己的神经网络然后将其用于数据预测。在这之前请确保你已经装好了Pytorch环境。关于神经网络的基本原理可以参照我之前写的博文小白也能看懂的最速神经网络入门顺便手搓一个神经网络1 Pytoch搭建神经网络的方式在Pytorch中神经网络有两种主流的搭建方式。通过继承torch.nn.Module类搭建神经网络推荐方式torch.nn.Module类提供了神经网络的整体框架包括一个可覆写的初始化函数和可覆写的前向传播函数forward最重要的是这个类提供了方向传播函数backward的实现这样我们就不需要根据反向传播算法自己手动实现反向传播部分的代码了自己写超级麻烦的参考我之前的博客就知道。具体步骤如下1编写一个神经网络类该类继承torch.nn.Module类也就是创建一个神经网络的框架2重写初始化函数在初始化函数中创建自己的神经网络中所需要用到的层相当于凑齐搭建这个网络所需的零件3重写forward函数在forward函数中定义2中的层的计算顺序相当于把2中的零件组装起来。我们用一个具体的例子试一试假设我们要利用Pytorch构建如下图所示的神经网络。上图的神经网络中有5个输入4个输出中间有三个全连接层。我们按照上述步骤构建一下这个网络。importtorchfromtorch.nnimportModule,Linear,ReLUclassMyNN(Module):def__init__(self):super().__init__()self.fc1Linear(5,7)self.fc2Linear(7,7)self.fc3Linear(7,4)defforward(self,x):xReLU()(self.fc1(x))xReLU()(self.fc2(x))xReLU()(self.fc3(x))returnxif__name____main__:#创建一个网络对象试试nnMyNN()print(nn)#可以查看一下模型结构inputtorch.rand(size(1,5))outnn(input)print(out)#输出看一下能否正确输出上面代码中使用Linear类构造全连接层其中有两个必要参数第一个是输入数据数量第二个是输出数据数量。由于整个网络输入数据是长度为5的向量因此第一个全连接层由Linear(5,7)定义。另外由于不确定用什么激活函数因此“无脑”直接用ReLU。可以看到__init__方法中定义了这个网络所用的所有层。forward方法中让输入数据依次经过fc1、fc2、fc3这三个全连接层。需要注意的是一定要让前一层的输出结构与下一层的输入结构一致。例如前一层输出的是长度为7的向量例如fc1层那么下一层的输入就必须是长度为7的向量例如fc2层。如果你对上面代码的运行过程还是不清楚这里再说明两件事情。1self.fc1(x)是什么意思self.fc1是一个Linear类对象在Python中像函数一样调用一个对象就是一个对象后面加括号这种写法指的就是调用这个对象的call方法。也就是说self.fc1(x)这种写法完全等价于self.fc1.call(x)。而在Linear类中call方法中写的就是这个Linear类的forward方法。因此self.fc1(x)意思就是让输入x经过self.fc1层的前向传播。后面类似这样的写法完全和上述是一样的意思。2为什么测试数据input的shape是(1,5)从图中或者代码实现可以看出nn这个网络接收的输入就是一个长度为5的一维向量其shape应该就是(5)。但是在Pytorch的前向传播中规定了第一个维度为batch_size。意思就是一次可以同时送batch_size个数据给这个网络进行前向传播计算这是为了提高数据计算的并行化从而尽可能提升计算速度。而我们这里是送1个数据进网络因此batch_size1从而input.shape(1,5)。上述方法是最灵活的网络构建方法推荐以后构建自己的神经网络尽可能使用这种方法。利用Squential对象构建网络这种方法仅使用于简单的小网络。这种方法是“顺序结构”的一层接一层无法实现分支结构。上面的网络如果用这种方法构建写法如下nntorch.nn.Sequential(Linear(5,7),ReLU(),Linear(7,7),ReLU(),Linear(7,4),ReLU())可以看到这种写法非常简单。直接使用torch.nn.Sequential类然后将模型中的层对象直接按照顺序写在Sequential类的参数中即可。网络构建好之后我们直接输出这个对象来查看其结构或者使用下面的方法来查看其中的权重、偏置参数。fornpinnn.named_parameters():print(np)2 神经网络的设计原则如果你看懂了这篇博文之前的内容那么现在你通过看神经网络结构图就已经能够将对应的神经网络在Pytorch中实现了。但是给你一个具体的任务你要怎么样确定神经网络的结构呢也就是说你要自己设计一个神经网络结构然后将它画出来。实际上这个问题不是一下就能回答出来的。就如同一个经验老到的画家你不可能刚刚学会线条、色彩搭配就能够做出完美的作品一样。神经网络的设计没有非常固定的范式在不同的场景下不同的应用下不同的客户要求下神经网络的结构可能都需要修改这是一件是非常吃经验的事情。这里我只能告诉大家一些基本的原则。首先神经网络的输入和输出结构是由数据确定的。假设我需要你设计一个神经网络用于预测每天的降雨量。假设现在你拿到的具体数据是之前360天的天气数据包括每天的“日期温度风速湿度风向”以及每天的“降雨量”。这就是你能拿到的训练数据其中输入x[日期温度风速湿度风向]输出y[降雨量]。显然这堆数据的输入是5个数输出是1个数。那么你构建的网络输入就必须是5个数输出必须是1个数。只有中间层是怎么样的那就只能看客户要求和经验了。学者们提出的注意力机制、Dropout层、各种激活函数、分支网络、多尺度特征提取等等都是为了更加优秀的预测性能。假设现在将当天和前一天的降雨量加入到考虑范畴并且要求你输出明天和后天的降雨量那么此时x[日期温度风速湿度风向当天降雨量前一天降雨量]y[明天的降雨量后天的降雨量]此时网络就要设计成7个元素的向量作为输入输出2个元素的向量。再比如现在要求你利用神经网络识别图像中的26个英文字母区分大小写假设你输入的图片是单通道32*32像素的灰度图那么你的网络的输入就应该是长度为102432×32的向量或者是一个32×32×1的矩阵。输出可以是一个数0表示a1表示b…26表示A27表示B…也可以是一个长度为52的向量向量中的每个元素表示属于某个字母的概率在实际使用中我们多采用这种方法。3 训练一个能够预测房价的神经网络我们已经学会了如何根据任务要求搭建神经网络。下面我们用一个具体的例子来试试神经网络的强大之处。我们使用神经网络来预测波士顿房价。首先让我们来看一下波士顿房价数据是什么样的。3.1 数据准备波士顿房价数据集当中的每条数据有以下14个属性CRIM-城镇人均犯罪率。ZN-占地面积超过 25,000 平方英尺的住宅用地比例。INDUS-每个城镇非零售商业用地的比例。CHAS-查尔斯河虚拟变量如果流域边界为河流则为1否则为0就是是不是江景房的意思NOX-氮氧化物浓度百万分之几RM-每套住宅的平均房间数AGE-1940年之前建造的自用住宅的比例DIS-波士顿五个就业中心的加权距离RAD-径向公路可达性指数就是里大路的距离TAX-每10000美元的全额房产税税率PTRATIO-城镇的师生比例B-黑人比例LSTAT-低收入人群比例MEDV-自有住房的中位数价格单位是1000美元这个是我们最终想要预测出来的量上述有些指标我们看不懂也没关系我只要知道波士顿房价MEDV受上面的13个变量的影响。波士顿房价数据集可以在这个地址免费下载到波士顿房价预测数据集下载之后数据集是CSV格式可以使用记事本或者表格工具打开结果如下我们现在要使用Python将数据集读取进来然后转换成Pytorch张量的形式。代码如下importcsvimporttorch data[]withopen(BostonHousing.csv,r)asf:readercsv.reader(f)next(reader)# 跳过表头如果没有表头就删掉这行forrowinreader:#将数据中的空字符串转换为0不然数值转换会出错row[0ifxelsexforxinrow]data.append([float(x)forxinrow])# string转floattensortorch.tensor(data)print(tensor.shape)#划分训练集和测试集#划分训练集和测试集train_settensor[0:300,:]val_settensor[300:400,:]test_settensor[400:,:]上述代码输出torch.Size([505, 14])说明我们一共得到了505条数据每条数据是有14个元素的向量其中最后一个元素是房价前13个分别是之前提到的影响房价的因素。然后我们将数据集划分为了训练集、验证集和测试集。3.2 神经网络设计数据准备好了现在可以开始来设计神经网络了。按照之前的设计思路这个神经网络应该是几个输入几个输出呢没错13个输入1个输出。那神经网络内部呢当前阶段我们可以随意设置我们就随意设置三个全连接层吧一个具有32个神经元一个具有64个神经元最后一个有1个神经元。注意最后这个必须是1个神经元因为输出是1个这个网络代码如下fromtorch.nnimportModule,Linear,ReLUclassBostonNN(Module):def__init__(self):super().__init__()self.fc1Linear(13,32)self.fc2Linear(32,64)self.fc3Linear(64,1)defforward(self,x):outReLU()(self.fc1(x))outReLU()(self.fc2(out))outReLU()(self.fc3(out))returnout上述神经网络仍然使用ReLU作为激活函数。接下来我们只要将这个网络训练起来即可。3.3 训练网络网络的训练实际上就是利用已有数据进行前向传播然后计算损失然后使用反向传播更新权重w和偏置b。这个过程如果不清楚可以回去看一下这篇博客小白也能看懂的最速神经网络入门顺便手搓一个神经网络现在我们还需要确定一下损失函数。波士顿房价最终输出的房价是一个数而且是连续的数这种在机器学习中叫做回归任务。具体的可以不用太理会你只需要知道我们要使用平均绝对误差或者均方误差来衡量。在这个例子中我们先使用均方误差Mean Square Error, MSE试一试。在正式开始训练之前我们要确定几件事情。我们使用Adam优化器他是梯度下降优化器的一种改进方案训练效果比较明显学习率我们先设置为0.001如果效果不好可以再调整。下面是整个训练代码。#划分训练集和测试集train_settensor[0:300,:]val_settensor[300:400,:]test_settensor[400:,:]#模型实例化然后设置基本参数nnBostonNN()loss_objMSELoss()#实例化MSE损失函数对象optimizertorch.optim.Adam(nn.parameters(),lr0.001)#指定优化器和学习率epoch50#训练的总次数foreinrange(epoch):nn.train()#设置为训练模式此时所有权重和偏置都可以被修改#正向传播y_prednn(train_set[:,0:13])#计算损失lossloss_obj(y_pred,train_set[:,13])#梯度下降optimizer.zero_grad()#清空上一轮的梯度loss.backward()#反向传播optimizer.step()#更新参数#到一定的epoch输出一下损失信息if(e1)%20:print(fEpoch [{epoch1}/{e}], Loss:{loss.item():.4f})上面的代码中我们指定了使用MSE损失设置了优化器为Adam指定学习率为0.001然后开始了训练循环。训练的过程和我之前手搓神经网络那一集是一样的也就是首先前向传播一次然后计算损失最后反向传播包括梯度计算和权重、偏置更新两个过程。当使用不同的参数时例如不同的优化器学习率和损失函数模型的训练结果、性能会不一样。具体怎么样选用这也是非常吃经验的事情。总之默认情况就是回归任务用均方误差分类任务用交叉熵。如果要改进甚至发明自己的损失函数那就是要写论文的事情了。3.4 模型的评估在训练过程中我们也可以在某一定的epoch去看看我们模型的性能。例如下面的代码利用验证集每隔100个epoch输出验证集上的绝对平均误差就是真实值减去预测值的绝对值。if(e1)%20:nn.eval()withtorch.no_grad():test_prednn(val_set[:,0:13])test_errortorch.mean(torch.abs(test_pred-val_set[:,13]))print(fTest MAE:{test_error:.4f})3.5 模型的使用模型训练好了我们可以用测试集试一试预测得准不准。#使用模型看看测试集前面10个数据预测得准不准outnn(test_set[0:10,0:13])print(真实房价,test_set[0:10,13].tolist())print(预测房价,out.tolist())print(预测的平均绝对误差,torch.mean(torch.abs(test_set[0:10,13]-out)).item())整体代码如下importcsvimporttorchfromtorch.nnimportModule,Linear,ReLU,MSELossclassBostonNN(Module):def__init__(self):super().__init__()self.fc1Linear(13,32)self.fc2Linear(32,64)self.fc3Linear(64,1)defforward(self,x):outReLU()(self.fc1(x))outReLU()(self.fc2(out))outReLU()(self.fc3(out))returnout data[]withopen(BostonHousing.csv,r)asf:readercsv.reader(f)next(reader)# 跳过表头如果没有表头就删掉这行forrowinreader:row[0ifxelsexforxinrow]#将数据中的空字符串转换为0不然数值转换会出错data.append([float(x)forxinrow])# string转floattensortorch.tensor(data)print(tensor.shape)#划分训练集和测试集train_settensor[0:300,:]val_settensor[300:400,:]test_settensor[400:,:]#模型实例化然后设置基本参数nnBostonNN()loss_objMSELoss()optimizertorch.optim.Adam(nn.parameters(),lr0.001)epoch50#训练的总次数foreinrange(epoch):nn.train()#设置为训练模式此时所有权重和偏置都可以被修改#正向传播y_prednn(train_set[:,0:13])#计算损失lossloss_obj(y_pred,train_set[:,13])#梯度下降optimizer.zero_grad()loss.backward()optimizer.step()#到一定的epoch输出一下损失信息if(e1)%20:print(fEpoch [{epoch1}/{e}], Loss:{loss.item():.4f})#到一定的epoch验证模型# 5. 评估if(e1)%20:nn.eval()withtorch.no_grad():test_prednn(val_set[:,0:13])test_errortorch.mean(torch.abs(test_pred-val_set[:,13]))print(fTest MAE:{test_error:.4f})#使用模型看看测试集前面10个数据预测得准不准outnn(test_set[0:10,0:13])print(真实房价,test_set[0:10,13].tolist())print(预测房价,out.tolist())print(预测的平均绝对误差,torch.mean(torch.abs(test_set[0:10,13]-out)).item())总结现在你已经会搭建任意全连接神经网络并且将其训练起来了。这样的神经网络可以处理任意的呈向量形式表达的数据。但是如果你需要处理图像这样的二维数据输入是一个矩阵甚至视频这样的三维数据输入是一个三维张量那就需要使用到卷积神经网络。喜欢的可以点个关注或者收藏下次还会更新卷积神经网络的使用。