提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
使用PyTorch解决深度学习中线性回归问题,需要理解问题的本质,先将具体问题抽象成数学问题。毕竟我们使用任何工具和编程语言来做开发,计算机都只能够解决数学问题。因此,我们在学这个内容之前,需要能够看清问题的本质(背后的数学问题是什么?)。
提示:以下是本篇文章正文内容,下面案例可供参考
一、线性回归解决什么问题?
如图所示,样本点在坐标中可视化结果。显然,不在一个直线上,但是我们需要拟合(找到)一条直线来最合理的说明这些数据,并且能够根据这个直线来预测其他数据。
上图数据根据公式 Y= 1.447*x + 0.0089 + e 生成。e代表噪声(任何数据在测量或观测读数时都会产生或大或小的误差,因此,即使数据是根据线性模型生成的,但是所有随机只是整体上展现出线性关系,而不是完全在一条直线上。所以我们的任务就是要找到一条最合适的直线来代表这些数据)
二、算法思想
1.构造目标函数
显然,我们要找到的模型是一个线性模型,那么我们可以假设该模型函数为:
Y= wX + b
根据我们已经获取了大量的数据集,每一个数据集都有对应的(x, y)。我们只需要得到合适的的w,b就能够确定一条我们需要的直线。
2.损失函数
这里要抛出一个问题:什么是损失函数?为什么需要损失函数?
先不急着回答这个问题。
根据中学所学知识,我们知道倒数可以用来确定函数的极值,也就是求最小值。
目前我们已知数据集所对应的(x, y),和一个不确定的直线函数。如果要引入最小值的思维来解决问题就是:
把每一个数据的x,带入到这条不确定的直线中所得到的y,与真实的y相比较,得到的差值最小。就意味着这条直线最符合我们需要的效果
正好,PyTorch工具可以帮助我们去解决求导问题,
也就意味着最小值不需要我们手动去算。解决了最小值问题也就能够找到合适的w、b。
有了w、b也就能够确定这条直线,我们的问题也就解决了。
Y= wX + b
数学表达就是:
loss = (wx + b)- y
当loss最小时,就是最接近的的时候
因此:
***损失函数:***是用来衡量求得的模型与真实数据的差距有多大,根据这个指标我们可以不断调整来求得最值。
三、代码实现
1.算法代码
import numpy as np
# 计算损失函数
def compute_error_for_line_given_points(w, b, points):
totalError = 0
for i in range(0, len(points)):
x = points[i, 0]
y = points[i, 1]
totalError += (y - (w * x + b)) ** 2 # 总损失
return totalError / float(len(points)) # 返回平均损失
# 梯度下降
def setp_gradient(w_current, b_current, points, learningRate):
b_gradient = 0
w_gradient = 0
N = float(len(points))
for i in range(0, len(points)):
x = points[i, 0]
y = points[i, 1]
w_gradient += -(2/N) * x * (y - ((w_current * x) + b_current))
b_gradient += -(2/N) * (y - ((w_current * x) + b_current))
new_w = w_current - (learningRate * w_gradient) # 当前值 - 学习率 * 梯度
new_b = b_current - (learningRate * b_gradient) # 当前值 - 学习率 * 梯度
return [new_w, new_b]
def gradient_descent_runner(points, starting_w, starting_b, learning_rate, num_iteration):
w = starting_w
b = starting_b
for i in range(num_iteration):
w, b = setp_gradient(w, b, np.array(points), learning_rate)
if i % 10 == 0:
print("当前w:{}, b:{}".format(w, b))
return [w, b]
def run():
points = np.genfromtxt("data.csv", delimiter=',')
learning_rate = 0.0001
initial_w = 0
initial_b = 0
num_iteration = 100000
print("开始梯度下降:w = {0}, b = {1}, error = {2}".format(initial_w, initial_b, compute_error_for_line_given_points(initial_w, initial_b, points) ))
print("Runing……")
[w, b] = gradient_descent_runner(points, initial_w, initial_b, learning_rate, num_iteration)
print("学习{0}之后 w= {1}, b = {2}, error = {3}".format(num_iteration, w, b, compute_error_for_line_given_points(w, b, points)))
if __name__ == "__main__":
run()
2.数据生成代码
此处使用 y = 1.557 * x + 2.4 + e生成数据,e是随机生成的噪声
import numpy as np
import csv
def generatorData(num_iteration):
x = np.random.uniform(0,100, size=(1000))
y = []
for i in range(len(x)):
yi = 1.557*x[i] + 2.4 + np.random.normal(0, 3)
y.append(yi)
data = []
for i in range(len(x)):
data.append([x[i], y[i]])
with open("data.csv", 'w', newline='') as file:
writer = csv.writer(file)
writer.writerows(data)
print("exit")
if __name__ =="__main__":
generatorData(1000)