1.深度学习线性模型实战

首先我们需要采样自真实模型的多组数据,对于已知真实模型的玩具样例,我们直接从指定的1.477,b=0.089的真实模型中直接采样:
y=1.477*x+0.089

1.采样数据

为了能够很好地模拟真实样本的观测误差,我们给模型添加误差自变量c,他采样自均值为0,方差为0.01的高斯分布: y=1.477x+0.089+c,c~N(0,0.01)
通过随机采样n=1000次,我们将获得n个样本的训练数据集:

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

循环进行100次采样,每次从区间[-10,10]的均匀分布U(0,1)中随机采样一个数据x,同时从均值为0,方差为0.01的高斯分布N(0,0.01)中随机采样噪声c,根据真实模型生成y的数据,并保存为Numpy数组。

2.计算误差

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

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
        #计算差的平方,并累加
        totalError+=(y-(w*x+b))**2
    #将累加的差求平均,得到均方差
    return totalError/float(len(points))

最后的误差和除以数据样本总数,从而得到每个样本上的均匀误差。

3.计算梯度

def step_gradient(b_current,w_current,points,lr):
    #计算误差函数在所有点上的导数,并更新w,b
    b_gradient=0
    w_gradient=0
    M=float(len(points))#样本总数
    for i in range(0,len(points)):
        x=points[i,0]
        y=points[i,1]
        #误差函数对b的导数:grad_b=2(wx+b-y)
        b_gradient+=(2/M)*((w_current*x+b_current)-y)
        #误差函数对w的导数:grad_w=2(wx+b-y)*x
        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)
    return [new_b,new_w]

4.梯度更新

在计算出误差函数在w和b处的梯度后,我们可以更新w和b的值。我们把对数据集的所有样本训练一次称为一个Epoch,共循环迭代nun_iterations个Epoch。实现如下·:

def gradient_descent(points,starting_b,starting_w,lr,num_iterations):
    #循环更新w,b多次
    b=starting_b#b的初始值
    w=starting_w#w的初始值
    #根据梯度下降算法更新多次
    for step in range(num_iterations):
        #计算梯度并更新一次
        b,w=step_gradient(b,w,np.array(points),lr)
        loss=mse(b,w,points)#计算当前的均方差,用于监控训练进度
        if step%50==0:
            print(f"iteration:{step},loss:{loss},w:{w},b:{b}")
    return [b,w]#返回最后一次的w,b
#主训练函数实现如下:
def main():
    #加载训练数据,这些数据是通过真实模型添加观测误差采样得到的
    lr=0.01#学习率
    initial_b=0#初始化b为0
    initial_w=0#初始化w为0
    num_iterations=1000
    #训练优化10000次,返回最有w*,b*和训练Loss的下降过程
    [b,w]=gradient_descent(data,initial_b,initial_w,lr,num_iterations)
    loss=mse(b,w,data)#计算最优数值解w,b上的均方差
    print(f'Final loss:{loss},w:{w},b:{b}')
main()

经过1000次的迭代更新后,保存最后的w,b的值,此时的w,b的值就是我们要找的w和b数值解

iteration:0,loss:6.458911187197308,w:1.0470826608700363,b:-0.024895206439208888
iteration:50,loss:0.012231851417018748,w:1.4743934052834653,b:0.04581304186951327
iteration:100,loss:0.010234870774880247,w:1.475195677423408,b:0.07636273814364132
iteration:150,loss:0.009956834723868128,w:1.475495031612,b:0.08776183713331556
iteration:200,loss:0.009918124260666244,w:1.4756067305303167,b:0.09201521682686217
iteration:250,loss:0.009912734671956979,w:1.4756484090797697,b:0.09360229303646986
iteration:300,loss:0.009911984289139204,w:1.4756639607208302,b:0.09419448350066095
iteration:350,loss:0.009911879814678599,w:1.4756697635508913,b:0.09441544928904334
iteration:400,loss:0.009911865268885885,w:1.4756719287781228,b:0.09449789891055516
iteration:450,loss:0.00991186324370113,w:1.4756727366957967,b:0.09452866358293818
iteration:500,loss:0.009911862961738266,w:1.47567303815652,b:0.09454014289660248
iteration:550,loss:0.009911862922481082,w:1.475673150641456,b:0.09454442620703604
iteration:600,loss:0.009911862917015393,w:1.4756731926132944,b:0.0945460244513917
iteration:650,loss:0.009911862916254417,w:1.4756732082743713,b:0.09454662080905933
iteration:700,loss:0.009911862916148444,w:1.4756732141180355,b:0.09454684332976875
iteration:750,loss:0.00991186291613371,w:1.4756732162984993,b:0.09454692635958253
iteration:800,loss:0.009911862916131638,w:1.4756732171121023,b:0.09454695734074381
iteration:850,loss:0.009911862916131366,w:1.4756732174156844,b:0.09454696890083658
iteration:900,loss:0.009911862916131328,w:1.4756732175289609,b:0.0945469732142884
iteration:950,loss:0.009911862916131296,w:1.475673217571228,b:0.0945469748237795
Final loss:0.009911862916131305,w:1.4756732175868124,b:0.0945469754172157

上述例子比较好的展示了梯度下降算法在求解模型参数上的强大之处。需要注意的是,对于复杂的非线性模型,通过梯度下降算法求解到w,b可能是局部极小值而非全局最小值解(个人理解:在定义域内,线性模型一定是单调的,而非线性模型可能不是单调的),这是有模型函数的非凸性决定的。但是我们在实践中发现,通过梯度下降算法求得的数值解,它的性能往往都能优化得很好,可以直接使用求解得到的数值解w和b来近似作为最优解。

发布了84 篇原创文章 · 获赞 0 · 访问量 2237

猜你喜欢

转载自blog.csdn.net/qq_43254375/article/details/104393909
今日推荐