当先锋百科网

首页 1 2 3 4 5 6 7

本节我们通过实战训练单输入神经元线性模型。首先我们需要采样自真实模型的多组数据,我们直接自从指定的w=1.477,b=0.089的真实模型中直接采样:
y = 1.477x+0.089

1、 采样数据
为了能够很好地模拟真实样本的观测误差,我们给模型添加误差自变量ε,它采样自均值为0,标准差为0.1 的高斯分布:
y=1.477x+0.089+ε, ε~N(0,0.1^2)
通过随机采样n = 1000 次,我们获得n个样本的训练数据集。代码如下:

data = []                            #保存样本集的列表
for i in range(100):                 #循环采样100个点
	x = np.random.uniform(-10., 10.)   #随机采样输入x
	# mean=0, std=0.1
    # 采样高斯噪声
	eps = np.random.normal(0., 0.1)
    #得到模型的输出
	y = 1.566 * x + 0.079 + eps
    #保存样本点
	data.append([x, y])
    #转换为2D Numpy数组
data = np.array(data)
np.savetxt("data.csv",data)

2、 计算误差
循环计算在每个点(x^(i), y^(j))处的预测值与真实值之间差的平方并累加,从而获得训练集上的均方误差损失值。代码如下

def mse(b, w, points):
    #根据当前的w,b参数计算均方差损失
    totalError = 0
    for i in range(0, len(points)):   #循环迭代所有点
        x = points[i, 0]              #获得i号点的输入x
        y = points[i, 1]              #获得i号的输出y
        # computer mean-squared-error
        #计算差的平方,并累加
        totalError += (y - (w * x + b)) ** 2
    # average loss for each point
    #将累加的误差求平均,得到均分差
    return totalError / float(len(points))

3、 计算梯度

def step_gradient(b_current, w_current, points, learningRate):
    #计算误差函数在所有点上的导数,并更新w,b
    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]
        # grad_b = 2(wx+b-y)
        #误差函数对b的导数:grad_b = 2(wx+b-y)
        b_gradient += (2/N) * ((w_current * x + b_current) - y)
        # grad_w = 2(wx+b-y)*x
        #误差函数对x的导数:grad_w = 2(wx+b-y)*x
        w_gradient += (2/N) * x * ((w_current * x + b_current) - y)
    # update w'
    #根据梯度下降算法更新w,b,其中learningRate 为学习率
    new_b = b_current - (learningRate * b_gradient)
    new_w = w_current - (learningRate * w_gradient)
    return [new_b, new_w]

4、 梯度更新
在计算出误差函数在w和b处的梯度后,我们根据梯度公式更新w和b的值。我们把对数据集的所有样本训练一次称为一个Epoch,共循环迭代 num_iterations 个 Epoch。代码如下:

def gradient_descent_runner(points, starting_b, starting_w, learning_rate, num_iterations):
    #循环更新w,b多次
    b = starting_b   #b的初始值
    w = starting_w   #w的初始值
    # update for several times
    #根据梯度下降算法更新多次
    for i in range(num_iterations):
        #计算梯度并更新一次
        b, w = step_gradient(b, w, np.array(points), learning_rate)
        loss = compute_error_for_line_given_points(b,w,points)
        if i%100 == 0:
            print(f"iterations:{i},loss:{loss},w:{w},b:{b}")
    return [b, w]   #返回最后一次的w,b

5、 主训练函数

def run():
	#加载训练集数据,这些数据是通过真实模型添加观测误差采样得到的
    points = np.genfromtxt("data.csv", delimiter=",")
    learning_rate = 0.01    #学习率
    initial_b = 0 # initial y-intercept guess   #初始化b为0
    initial_w = 0 # initial slope guess         #初始化w为0
    num_iterations = 1000
    #训练优化1000次,返回最优w,b和训练Loss的下降过程
    [b, w] = gradient_descent_runner(data, initial_b, initial_w, learning_rate, num_iterations)
    loss = compute_error_for_line_given_points(b, w, data)
    print(f'Final loss:{loss},w:{w},b:{b}')
if __name__ == '__main__':
    run()

经过 1000 的迭代更新后,保存最后的w和b值,此时的w和b的值就是我们要找的数值解。运行结果如下:
在这里插入图片描述