损失函数可视化

对于 m m m个样本,使用MSE最为损失函数。

如果样本只有一个属性 x i x_i xi,那么损失函数为:
L = 1 m ∑ i ( w ∗ x i + y i ) 2 L=\frac{1}{m}\sum_i(w*x_i+y_i)^2 L=m1i(wxi+yi)2
我们来画出该损失函数的图像:

import numpy as np
import matplotlib.pyplot as plt

def image(b=0):
    dense = 400
    w = np.linspace(-2,4,dense)
    x_train = np.array([0,   1,	  2,   3,   4,   5])
    y_train = np.array([1.1, 2.2,  3.8, 4.1, 4.9, 5.2])


    for i in range(dense):
        loss = np.square(w[i] * x_train+b - y_train).sum() / len(x_train)
        plt.scatter(w[i],loss,s=1)

    plt.title('Loss Func Line')
    plt.xlabel('w')
    plt.ylabel('loss')
    plt.axis([0,3,0,10])
    plt.axhline(y=1, ls=":", c="black")
    plt.axhline(y=2, ls=":", c="black")
    plt.axhline(y=4, ls=":", c="black")
    plt.axhline(y=7, ls=":", c="black")
    plt.show()

image()

图1
图1中偏置$b=0$,平行于$x$轴的是损失函数等高线。 加上偏置:
image(0.5) image(1)
image(1.7) image(2.5)

可以看到偏置 b b b的改变直接影响了损失函数的最小值以及对应的 w w w

上面我们是固定住 b b b w w w和loss的股谚息。现在我们在3维坐标中画出权重 w w w和偏置 b b b对应的loss:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  # Axes3D 包含的是实现3d绘图的各种方法


x_train = np.array([0,   1,	  2,   3,   4,   5])
y_train = np.array([1.1, 2.2,  3.8, 4.1, 4.9, 5.2])

dense = 400
w,b = np.meshgrid(np.linspace(-2,4, dense),np.linspace(-7,10, dense))

# y = wx+b
def get_loss_value(w,b):
    return np.square(w*x_train+b - y_train).sum()/len(x_train)

def loss_point():
    loss_list = []
    for i in range(dense):
        loss_list2=[]
        for j in range(dense):
            loss = get_loss_value(w[i][j], b[i][j])
            loss_list2.append(loss)
        loss_list.append(loss_list2)
    return loss_list



fig = plt.figure()
ax = Axes3D(fig)
loss = np.array(loss_point())

# 添加坐标轴(顺序是Z, Y, X)
ax.set_xlabel('w')
ax.set_ylabel('b')
ax.set_zlabel('L')
ax.plot_surface(w, b, loss, rstride=30,cstride=30, cmap='jet')
plt.show()

在这里插入图片描述

图2
上面一共计算了400*400=160000个loss值,那么这么多loss值中哪些是相同的呢?我们把这样的点画在$w$和$b$组成的二维空间中是什么样子的?
import numpy as np
import matplotlib.pyplot as plt

x_train = np.array([0,   1,	  2,   3,   4,   5])
y_train = np.array([1.1, 2.2,  3.8, 4.1, 4.9, 5.2])

dense = 400

# y = wx+b
def get_loss_value(w,b):
    return np.square(w*x_train+b - y_train).sum()/len(x_train)


w = np.linspace(-2,4,dense)
b = np.linspace(-7,10,dense)

def draw_contour_line(dense,isoheight): #dense表示取值的密度,isoheight表示等高线的值
    list_w = []
    list_b = []
    list_loss = []
    for i in range(dense):
        for j in range(dense):
            loss = get_loss_value(w[i],b[j])
            if 1.05*isoheight>loss>0.95*isoheight:
                list_w.append(w[i])
                list_b.append(b[j])
            else:
                pass
    plt.scatter(list_w,list_b,s=1) #s=0.25比较合适

draw_contour_line(dense,1)
draw_contour_line(dense,4)
draw_contour_line(dense,7)
draw_contour_line(dense,10)
draw_contour_line(dense,20)
draw_contour_line(dense,30)
draw_contour_line(dense,50)
draw_contour_line(dense,100)
draw_contour_line(dense,200)
plt.title('Loss Func Contour Line')
plt.xlabel('w')
plt.ylabel('b')
plt.axis([-2,4,-7,10])
plt.show()

图3:参数空间中的损失等高线

图3和我们预期也是一样的,图3就好比是用一个平行于图2中 w o b wob wob平面沿着L轴做切面,切面所触及的点的loss都是相等的。由图2也能感知当loss<20都可出现椭圆形等高线,当loss较大时候就不在是椭圆形了。

所以我们在学习梯度下降算法的时候经常看到这样的图:

这张图后面一般都会再接一句,梯度下降的方向与等高线的切线方向垂直。

可以看到参数空间上点的变化相当于损失函数的”上坡”或”下坡“。

参考文章:
https://blog.csdn.net/keeppractice/article/details/105620966
梯度方向与等高线方向垂直的理解

猜你喜欢

转载自blog.csdn.net/weixin_38052918/article/details/108032973
今日推荐