极为简单(基础)的线性神经网络模型

  • 数据采集
  • 误差计算
  • 梯度计算
  • 方程更新
  • 函数的调用及运行结果



本文引入的库只有一个numpy,用的损失算法是MSE(平方误差损失),优化算法是就用了一个很简单的梯度下降。应该是神经网络入门级别的例子。静下心来好好看,就应该能够稍微消除一点对编写神经网络这项可望不可及的技能的恐惧。


本文将分为数据采集、误差计算、梯度计算、方程更新四个方面着手,并在最后给出运行结果及全部代码的整合。

数据采集

本文的将随机采集100个数据,并假设误差变量属于正态分布进行试验
代码如下:

# 采集数据
data = []
# 循环采样100个点
for i in range(100):
    x = np.random.uniform(-10, 10)  # uniform:随机生成一个实数
    eps = np.random.normal(0., 0.01)  # normal:正态分布
    y = 1.477 * x + 0.089 + eps
    data.append([x, y])
data = np.array(data)

误差计算

通过方差公式计算误差,可适用于线性的模型
代码如下:

# 计算误差
def mse(b, w, points):
    """

    :param b:  b的值
    :param w:  w的值
    :param points:  [x,y]的数据集
    :return:  误差值
    """
    # 设置初始误差为0
    totalError = 0
    # 循环遍历所有数据
    for i in range(0, len(points)):
        # 获取第i个位置的x的值
        x = points[i, 0]
        # 获取第i个位置的y的值
        y = points[i, 1]
        # 计算总误差
        totalError += (y - (w * x + b)) ** 2
    # 获得平均方差(误差)
    return totalError / float(len(points))

梯度计算

梯度计算公式如下:

线性神经网络输入输出 线性神经网络模型_python

代码如下:

# 计算梯度
def step_gradient(b_current, w_current, points, lr):
    """

    :param b_current: b的值
    :param w_current: w的值
    :param points: [x,y]的数据集
    :param lr: 学习速度
    :return: 更新后的b和w的值组成的数组[b,w]
    """
    # 设置初始变量
    b_gradient = 0
    w_gradient = 0
    M = float(len(points))
    # 遍历所有数据
    for i in range(0, len(points)):
        # 计算b的梯度
        b_gradient += (2 / M) * ((w_current * x + b_current) - y)
        # 计算w的梯度
        w_gradient += ((2 / M) * x * ((w_current * x + b_current) - y))
    # 更新w和b的值,lr为学习率
    new_b = b_current - (lr * b_gradient)
    new_w = w_current - (lr * w_gradient)
    # 返回新得到的w和b的值
    return [new_b, new_w]

方程更新

循环训练不断更新w和b的值,并计算出误差大小。每50次训练打印出相关数据。
具体代码如下:

# 更新w和b的值
def gradient_descent(points, starting_b, starting_w, lr, num_iterations):
    """

    :param points: [x,y]的数据集
    :param starting_b: b的初始值
    :param starting_w: w的初始值
    :param lr: 学习速度
    :param num_iterations: 学习次数
    :return: 更新后的[b, w}
    """
    b = starting_b
    w = starting_w
    # 循环训练
    for step in range(num_iterations):
        # 调用step_gradient函数更新b,w的值
        if step % 50 == 0:
            print(f"w:{w},b:{b}")
        b, w = step_gradient(b, w, np.array(points), lr)
        # 计算误差
        loss = mse(b, w, points)
        # 每50个打印一下loss ,w ,b的值
        if step % 50 == 0:
            print(f"iteration:{step},loss:{loss},w:{w},b:{b}")
    return [b, w]

函数的调用及运行结果

代码如下:

# 主函数
def main():
    # 设置学习速度
    lr = 0.01
    # 设置初始b值
    initial_b = 0
    # 设置初始w值
    initial_w = 0
    # 设置训练次数
    num_iterations = 1000
    # 得到最优的b和w的值
    b, w = gradient_descent(data, initial_b, initial_w, lr, num_iterations)
    # 计算当最优值解w和b时的误差
    loss = mse(b, w, data)
    # 打印误差值和b以及w的值
    print(f"Final loss:{loss},w:{w},b:{b}")


main()

结果如下:

w:0,b:0
iteration:0,loss:50.97753728816465,w:2.773969394653172,b:0.2871579814227153
w:1.4670253907341861,b:0.1518647071993988
iteration:50,loss:0.003996092455715741,w:1.4736812030648103,b:0.15255370890117476
w:1.4705453451013133,b:0.1522290886495735
iteration:100,loss:0.004626595698334646,w:1.4705613149378474,b:0.15223074182787877
w:1.4705537908165853,b:0.1522299629398788
iteration:150,loss:0.00462881626037251,w:1.4705538291343245,b:0.15222996690648516
w:1.4705538110810834,b:0.15222996503763542
iteration:200,loss:0.004628821592423818,w:1.4705538111730216,b:0.15222996504715275
w:1.4705538111297045,b:0.1522299650426685
iteration:250,loss:0.004628821605217145,w:1.4705538111299266,b:0.15222996504269148
w:1.4705538111298213,b:0.1522299650426807
iteration:300,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:350,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:400,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:450,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:500,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:550,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:600,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:650,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:700,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:750,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:800,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:850,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:900,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
w:1.4705538111298213,b:0.1522299650426807
iteration:950,loss:0.004628821605247868,w:1.470553811129823,b:0.15222996504268085
Final loss:0.004628821605248407,w:1.4705538111298213,b:0.1522299650426807

可以看出在第50次训练左右,w和b的值就已经离给定值相差不远

下面给出全部代码:

import numpy as np

# 采集数据
data = []
# 循环采样100个点
for i in range(100):
    x = np.random.uniform(-10, 10)  # uniform:随机生成一个实数
    eps = np.random.normal(0., 0.01)  # normal:正态分布
    y = 1.477 * x + 0.089 + eps
    data.append([x, y])
data = np.array(data)


# 计算误差
def mse(b, w, points):
    """

    :param b:  b的值
    :param w:  w的值
    :param points:  [x,y]的数据集
    :return:  误差值
    """
    # 设置初始误差为0
    totalError = 0
    # 循环遍历所有数据
    for i in range(0, len(points)):
        # 获取第i个位置的x的值
        x = points[i, 0]
        # 获取第i个位置的y的值
        y = points[i, 1]
        # 计算总误差
        totalError += (y - (w * x + b)) ** 2
    # 获得平均方差(误差)
    return totalError / float(len(points))


# 计算梯度
def step_gradient(b_current, w_current, points, lr):
    """

    :param b_current: b的值
    :param w_current: w的值
    :param points: [x,y]的数据集
    :param lr: 学习速度
    :return: 更新后的b和w的值组成的数组[b,w]
    """
    # 设置初始变量
    b_gradient = 0
    w_gradient = 0
    M = float(len(points))
    # 遍历所有数据
    for i in range(0, len(points)):
        # 计算b的梯度
        b_gradient += (2 / M) * ((w_current * x + b_current) - y)
        # 计算w的梯度
        w_gradient += ((2 / M) * x * ((w_current * x + b_current) - y))
    # 更新w和b的值,lr为学习率
    new_b = b_current - (lr * b_gradient)
    new_w = w_current - (lr * w_gradient)
    # 返回新得到的w和b的值
    return [new_b, new_w]


# 更新w和b的值
def gradient_descent(points, starting_b, starting_w, lr, num_iterations):
    """

    :param points: [x,y]的数据集
    :param starting_b: b的初始值
    :param starting_w: w的初始值
    :param lr: 学习速度
    :param num_iterations: 学习次数
    :return: 更新后的[b, w}
    """
    b = starting_b
    w = starting_w
    # 循环训练
    for step in range(num_iterations):
        # 调用step_gradient函数更新b,w的值
        if step % 50 == 0:
            print(f"w:{w},b:{b}")
        b, w = step_gradient(b, w, np.array(points), lr)
        # 计算误差
        loss = mse(b, w, points)
        # 每50个打印一下loss ,w ,b的值
        if step % 50 == 0:
            print(f"iteration:{step},loss:{loss},w:{w},b:{b}")
    return [b, w]


# 主函数
def main():
    # 设置学习速度
    lr = 0.01
    # 设置初始b值
    initial_b = 0
    # 设置初始w值
    initial_w = 0
    # 设置训练次数
    num_iterations = 1000
    # 得到最优的b和w的值
    b, w = gradient_descent(data, initial_b, initial_w, lr, num_iterations)
    # 计算当最优值解w和b时的误差
    loss = mse(b, w, data)
    # 打印误差值和b以及w的值
    print(f"Final loss:{loss},w:{w},b:{b}")


main()