基于Pytorch的机器学习Regression问题实例(附源码)

简介: 基于Pytorch的机器学习Regression问题实例(附源码)

一、写在前面

声明

本人既是Python新手也是机器学习新手,以下内容主要是为了作者自己的学习记录以及与他人的学习沟通。如果其中有错误,非常欢迎指正。如果误导了别人,那就非常抱歉了。。。。

本文目的

机器学习由于在声音、图像识别等等领域应用非常广泛,近年来是一个非常火热的发展方向。但是纵观各种学习书籍、视频等资料,要么先用大篇幅的文字讲了机器学习的理论但是没什么实践,要么直接用一些比较复杂的DNN或者CNN开始进行Demo,导致新手从入门到放弃。

本文希望从最简单的NN开始入手做一个Demo,不妨作为机器学习最开始的起点,然后再学习更复杂的机器学习理论。

学前准备

虽然上面说了本文可以作为机器学习最开始的起点,但是在此之前还是需要了解下机器学习的基本概念。个人非常推荐下面的文章:

【转】机器学习入门——浅谈神经网络

如果不会用笔算神经元网络就不算真正懂神经元网络

二、构建神经元网络

要解决什么问题

一个典型的Regression问题:我们已经有20个坐标点,要用一个神经元网络来拟合这20个坐标点,并且能预测后面的趋势走向。

打开上帝视角:我们预测的函数是y = x*sin(x),前20个坐标点即为x在0~2π等分的20个点。当然,这在实际问题中我们不可能会知道我们要拟合和预测的是什么。

构建Python代码

神经元网络基本参数:

训练次数为100;

Learningrate为0.1;

优化方式为随机梯度下降(SGD);

激活函数为Relu;

输入层神经元数=1;

隐藏层神经元数=6;

输出层神经元数=1;

loss函数为均方差(MSE);

这真的是可以称为最简单的“神经元网络”了。。。

源代码如下,其实只要不到50行代码就可以了,细节请见代码备注。

import torch
import matplotlib.pyplot as plt
import math
import numpy

pi = math.pi

#导入训练组数据
x_train = numpy.arange(0,2*pi,pi/10)
y_train = x_train * numpy.sin(x_train)

#把x,y包装成tensor(神经元网络计算的输入只能是tensor或者variable)
x_train = torch.tensor(x_train, dtype=torch.float32)  #转换数据格式,要不然默认double会报错!!!
y_train = torch.tensor(y_train, dtype=torch.float32)
x_train = torch.unsqueeze(x_train,dim=1)   #array格式转换成tensor,并且要升一个维度(这样神经元网络才知道输入的是20个1维的学习数据,而不是1个20维的学习数据)!!!
y_train = torch.unsqueeze(y_train,dim=1)

#构建神经元网络
class NN(torch.nn.Module):
    def __init__(self,input_n,hidden1_n,output_n):  #input_n=输入层神经元数量(这个例子中是1),hidden1_n=第一个隐藏层神经元数量,output_n输出层神经元数量(这个例子中是1)
        super(NN, self).__init__()  #继承父class torch.nn.Module
        self.input = torch.nn.Linear(input_n,hidden1_n)    #构建输入层
        self.predict = torch.nn.Linear(hidden1_n,output_n)   #构建输出层

    def forward(self,x):
        x_mid = torch.relu(self.input(x))
        y = self.predict(x_mid)
        return y

nn = NN(1,6,1)
# print(nn)   #验证一下上面的代码是否会报错

optimizer = torch.optim.SGD(nn.parameters(),lr=0.1)  #优化方法为随机梯度下降
loss_f = torch.nn.MSELoss()

for i in range(100):  #训练100次
    y_predict = nn.forward(x_train)
    loss = loss_f(y_predict,y_train)
    optimizer.zero_grad() #这三句话用于优化learningrate,不写的话上面的SGD就没用了
    loss.backward()
    optimizer.step()

x_train = x_train.detach().numpy()  #把tensor型的张量数据再还原成numpy,要不然不能画图啊
y_train = y_train.detach().numpy()
y_predict = y_predict.detach().numpy()

plt.plot(x_train,y_train)  #画图看一下
plt.scatter(x_train,y_predict)
plt.show()
运行结果

这样,我们构建的神经元网络输出结果(x_train,y_predict)就是下图了

BUT!!!

我们打开上帝视角看看,就会发现,上面的神经元网络得到的学习结果不仅不准,而且还不稳定(每次run的结果都不一样)。

我忘了把每个图的loss放进来了,大家可以在源码上加print(loss),看看loss和各个图形的关系

所以说,机器学习算是一种工程,需要实践出真知。下面再一起优化下这个神经元网络。

三、优化神经元网络

下面我们就用几种方法来使神经元网络能够有效地达“回归”的目的。

下面的每个方法,都是基于上一个方法进行的优化。

增加学习次数

上面每次学习的结果波动都很大,直观的感觉就是欠拟合。那么把学习次数由100次增加到10000次再看看。

貌似结果好了一些,loss=1.7608。(学习次数100次的时候,loss=3~5)但是结果仍然很“粗糙”,波动也仍然较大。

把学习次数再增大100倍,到1000000,我的电脑就算不出来了。仅通过增大学习次数这种“蛮力”难以解决真正的技术问题,而且还会导致过拟合

调整LearningRate

以下是LearningRate=0.01的结果

感觉不错,有内味了,loss=1.1876。

多运行几次我找到的最好结果如下

loss=0.2911。

这样就满意了?of course not!

调整优化方式

SGD(随机梯度下降)算是一种比较基础的优化算法(但是不妨碍它应用广泛),我们换成Adam试试。

关于不同的优化算法,再推荐一篇文章:深度学习各种优化函数详解

优化函数换成Adam后波动会小一些,上图的loss=0.9935,但是学习次数调回到了200。运行了很多次总结一下loss=0.2~2左右

上面用SGD方法的loss=0.2~3左右,但是学习次数是10000的前提。

但我觉得就在这个例子中,并不能说明哪个优化算法是更好的,为了节省时间,后面的算法基于Adam优化方法,学习200次再进行更新。

激活函数

Relu相对而言是个比较简单的激活函数,现在应用比较广泛的应该是Sigmoid函数,那我们就换成Sigmoid再试试。

这里就不上图了,运行结果loss=1.5~2.5左右。看起来波动(variation)和偏差(bias)都没有什么改善(甚至更差了)。

小结

其实我也是第一次比较系统的实操Pytorch,到目前为止好像只有在调整LearningRate之后,模型的loss有了比较明显的改善,后面的方法好像都作用不大。

有点后悔选用y=x*sin(x)这个目标,它似乎有点简单了,如果用更加复杂的目标函数,或许能看出来其他参数调整的作用

事已至此,有没有发现什么不对?

那就是无论怎么调整参数,虽然loss有改善,但是这个神经元网络输出的结果,就像是几条直线拼接出来的“生硬的”模型。仔细想想,这倒也合理,毕竟这个网络的神经元数,去掉输出输出层,只有一层隐藏层的6个神经元。

接下来搞点不一样的!

四、增加神经元个数

我们把原来隐藏层的6个神经元,增加到18个试试!

BUT!

增加神经元,要怎么加?它应该更瘦高还是更矮胖?那我们就都试一下。

Fat Learning(这个名字是我编的,如有雷同,纯属巧合)

网络结构变成:输入层=1,隐藏层=18,输出层=1

它看起来好像没那么“生硬”了,上图loss=0.99,整体loss=1.0~1.85左右。

我们玩个狠的,把隐藏层由18增加到100,loss=0.91,结果如下图。

说实话,我对你有些失望

Deep Learning

网络结构变成:输入层=1,隐藏层1=6,隐藏层2=6,隐藏层3=6,输出层=1

这里要对代码做一下比较大的调整

class NN(torch.nn.Module):
    def __init__(self,input_n,hidden1_n,hiddem2_n,hidden3_n, output_n):
        super(NN, self).__init__()  #继承父class torch.nn.Module
        self.input = torch.nn.Linear(input_n,hidden1_n)    #构建输入层
        self.hidden1 = torch.nn.Linear(hidden1_n,hiddem2_n)  #构建中间隐藏层
        self.hidden2 = torch.nn.Linear(hiddem2_n,hidden3_n)  #构建中间隐藏层
        self.predict = torch.nn.Linear(hidden3_n,output_n)   #构建输出层

    def forward(self,x):
        x_mid1 = torch.sigmoid(self.input(x))
        x_mid2 = torch.sigmoid(self.hidden1(x_mid1))
        x_mid3 = torch.sigmoid(self.hidden2(x_mid2))
        y = self.predict(x_mid3)
        return y

运行结果如上图,loss=0.56,整体loss=0.55~0.65,算是有个质变了。

这里也算间接地回答了一个问题,Why Deep Learning?

五、进行预测

对给定的数据进行拟合(回归)是这个神经元网络的基本任务,但是我们说到底还是想看看训练好的神经元网络进行“预测”的能力怎么样。

如开始所述,我们的train组数据是x在0~2π等分的20个点。

接下来,我们用x在0~4π等分4*7=28个点来验证下预测的结果准不准

实际结果有点欲哭无泪,这个神经元网络在2π~4π的情况下预测的结果并不准。。。

这个预测问题,很遗憾,我没有搞定。。。。(讽刺的是我前面居然还认为y=x*sin(x)太简单了。。)

我尝试改了一个1×9×9×9×9×9×9×1的网络,但是结果和上面差不多。。。

如果有更好的方法,拜托教教我,先付优化后的代码为敬

六、完整代码

import torch
import matplotlib.pyplot as plt
import math
import numpy

pi = math.pi

#导入训练组数据
x_train = numpy.arange(0,2*pi,pi/10)
y_train = x_train * numpy.sin(x_train)


#把x,y包装成tensor(神经元网络计算的输入只能是tensor或者variable)
x_train = torch.tensor(x_train, dtype=torch.float32)  #转换数据格式,要不然默认double会报错!!!
y_train = torch.tensor(y_train, dtype=torch.float32)
x_train = torch.unsqueeze(x_train,dim=1)   #array格式转换成tensor,并且要升一个维度(这样神经元网络才知道输入的是20个1维的学习数据,而不是1个20维的学习数据)!!!
y_train = torch.unsqueeze(y_train,dim=1)


#构建神经元网络
class NN(torch.nn.Module):
    def __init__(self,input_n,hidden1_n,hidden2_n,hidden3_n,hidden4_n,hidden5_n,hidden6_n, output_n):
        super(NN, self).__init__()  #继承父class torch.nn.Module
        self.input = torch.nn.Linear(input_n,hidden1_n)    #构建输入层
        self.hidden1 = torch.nn.Linear(hidden1_n,hidden2_n)  #构建中间隐藏层
        self.hidden2 = torch.nn.Linear(hidden2_n,hidden3_n)  #构建中间隐藏层
        self.hidden3 = torch.nn.Linear(hidden3_n, hidden4_n)
        self.hidden4 = torch.nn.Linear(hidden4_n, hidden5_n)
        self.hidden5 = torch.nn.Linear(hidden5_n, hidden6_n)
        self.predict = torch.nn.Linear(hidden6_n,output_n)   #构建输出层

    def forward(self,x):
        x_mid1 = torch.sigmoid(self.input(x))
        x_mid2 = torch.sigmoid(self.hidden1(x_mid1))
        x_mid3 = torch.sigmoid(self.hidden2(x_mid2))
        x_mid4 = torch.sigmoid(self.hidden3(x_mid3))
        x_mid5 = torch.sigmoid(self.hidden4(x_mid4))
        x_mid6 = torch.sigmoid(self.hidden5(x_mid5))
        y = self.predict(x_mid6)
        return y

nn = NN(1,9,9,9,9,9,9,1)
print(nn)   #确认一下网络结构

optimizer = torch.optim.Adam(nn.parameters(),lr=0.01)  #优化方法为Adam下降
loss_f = torch.nn.MSELoss()

for i in range(500):  #训练100次
    y_predict = nn.forward(x_train)
    loss = loss_f(y_predict,y_train)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()


x_train = x_train.detach().numpy()  #把tensor型的张量数据再还原成numpy,要不然不能画图啊
y_train = y_train.detach().numpy()
y_predict = y_predict.detach().numpy()

print(loss)

#--------------------------------以下是用训练好的神经元网络进行预测-----------------------------------------------
x_test = numpy.arange(0*pi,4*pi,pi/7)
x_test = torch.tensor(x_test, dtype=torch.float32)
x_test = torch.unsqueeze(x_test,dim=1)

y_test = nn.forward(x_test)
x_test = x_test.detach().numpy()
y_test = y_test.detach().numpy()

x_plot = numpy.arange(0,4*pi,pi/10)
y_plot = x_plot * numpy.sin(x_plot)

plt.plot(x_plot,y_plot)
plt.scatter(x_train,y_predict)
plt.scatter(x_test,y_test)

plt.show()


七、预测问题解决

对于上文中全连接神经元网络模型存在的“预测不准”问题,在另一篇文章中,用RNN基本算是解决了:基于Numpy构建RNN模块并进行实例应用(附代码)


相关文章
|
18天前
|
PyTorch Shell API
Ascend Extension for PyTorch的源码解析
本文介绍了Ascend对PyTorch代码的适配过程,包括源码下载、编译步骤及常见问题,详细解析了torch-npu编译后的文件结构和三种实现昇腾NPU算子调用的方式:通过torch的register方式、定义算子方式和API重定向映射方式。这对于开发者理解和使用Ascend平台上的PyTorch具有重要指导意义。
|
4月前
|
机器学习/深度学习 并行计算 PyTorch
优化技巧与策略:提高 PyTorch 模型训练效率
【8月更文第29天】在深度学习领域中,PyTorch 是一个非常流行的框架,被广泛应用于各种机器学习任务中。然而,随着模型复杂度的增加以及数据集规模的增长,如何有效地训练这些模型成为了一个重要的问题。本文将介绍一系列优化技巧和策略,帮助提高 PyTorch 模型训练的效率。
409 0
|
2月前
|
并行计算 开发工具 异构计算
在Windows平台使用源码编译和安装PyTorch3D指定版本
【10月更文挑战第6天】在 Windows 平台上,编译和安装指定版本的 PyTorch3D 需要先安装 Python、Visual Studio Build Tools 和 CUDA(如有需要),然后通过 Git 获取源码。建议创建虚拟环境以隔离依赖,并使用 `pip` 安装所需库。最后,在源码目录下运行 `python setup.py install` 进行编译和安装。完成后即可在 Python 中导入 PyTorch3D 使用。
283 0
|
4月前
|
机器学习/深度学习 并行计算 PyTorch
PyTorch与CUDA:加速深度学习模型训练的最佳实践
【8月更文第27天】随着深度学习应用的广泛普及,高效利用GPU硬件成为提升模型训练速度的关键。PyTorch 是一个强大的深度学习框架,它支持动态计算图,易于使用且高度灵活。CUDA (Compute Unified Device Architecture) 则是 NVIDIA 开发的一种并行计算平台和编程模型,允许开发者直接访问 GPU 的并行计算能力。本文将详细介绍如何利用 PyTorch 与 CUDA 的集成来加速深度学习模型的训练过程,并提供具体的代码示例。
188 1
|
5月前
|
机器学习/深度学习 自然语言处理 数据挖掘
机器学习不再是梦!PyTorch助你轻松驾驭复杂数据分析场景
【7月更文挑战第31天】机器学习已深深嵌入日常生活,从智能推荐到自动驾驶皆为其应用。PyTorch作为一个开源库,凭借简洁API、动态计算图及GPU加速能力,降低了学习门槛并提高了开发效率。通过一个使用PyTorch构建简单CNN识别MNIST手写数字的例子,展现了如何快速搭建神经网络。随着技能提升,开发者能运用PyTorch及其丰富的生态系统(如torchvision、torchtext和torchaudio)应对复杂场景,如自然语言处理和强化学习。掌握PyTorch,意味着掌握了数据时代的关键技能。
46 1
|
5月前
|
机器学习/深度学习 数据采集 PyTorch
PyTorch模型训练与部署流程详解
【7月更文挑战第14天】PyTorch以其灵活性和易用性在模型训练与部署中展现出强大的优势。通过遵循上述流程,我们可以有效地完成模型的构建、训练和部署工作,并将深度学习技术应用于各种实际场景中。随着技术的不断进步和应用的深入,我们相信PyTorch将在未来的机器学习和深度学习领域发挥更加重要的作用。
|
5月前
|
机器学习/深度学习 并行计算 PyTorch
PyTorch | 加速模型训练的妙招
PyTorch | 加速模型训练的妙招
53 0
|
6月前
|
机器学习/深度学习 人工智能 数据处理
人工智能平台PAI产品使用合集之PAI-DSW实例服务器ping不通google.com,该如何排查
阿里云人工智能平台PAI是一个功能强大、易于使用的AI开发平台,旨在降低AI开发门槛,加速创新,助力企业和开发者高效构建、部署和管理人工智能应用。其中包含了一系列相互协同的产品与服务,共同构成一个完整的人工智能开发与应用生态系统。以下是对PAI产品使用合集的概述,涵盖数据处理、模型开发、训练加速、模型部署及管理等多个环节。
|
6月前
|
机器学习/深度学习 算法 Python
【机器学习】集成学习在信用评分领域实例
【机器学习】集成学习在信用评分领域实例
142 1
|
6月前
|
机器学习/深度学习 人工智能 自然语言处理
【机器学习】贝叶斯算法在机器学习中的应用与实例分析
【机器学习】贝叶斯算法在机器学习中的应用与实例分析
566 1