在上一篇博客:
tensorflow2.0实现鸢尾花数据集的分类(2)——神经网络搭建
笔者在结尾留了一个问题,今天我们就来解释一下
我们搭建神经网络比较重要的一步是前向传播,这一步少了一点东西,我们是这样做得:
with tf.GradientTape() as tape:
#前向传播计算 y, y为预测结果
y = tf.matmul(x_train, w) + b
# 计算损失函数
loss = (y - y_train)**2
loss = tf.reduce_mean(loss, axis=0)
你可能会说,对啊,这没错啊,神经网络模型不就是: y = x ∗ w + b y = x*w + b y=x∗w+b,这么做有什么错吗??
那我再举一个例子:如果搭建两层神经网络:
y 1 = x ∗ w 1 + b 1 ( 1 ) y 2 = y 1 ∗ w 2 + b 2 ( 2 ) y_1 = x*w_1 + b_1\qquad(1)\\ y_2 = y_1 * w_2 + b_2\qquad(2) y1=x∗w1+b1(1)y2=y1∗w2+b2(2)
那么模型的表达力一定会增强吧?!
答案是否定的
将式 ( 1 ) (1) (1)带入式 ( 2 ) (2) (2)中,你会发现:
y 2 = y 1 ∗ w 2 + b 2 = ( x ∗ w 1 + b 1 ) ∗ w 2 + b 2 = x ∗ ( w 1 ∗ w 2 ) + ( b 1 ∗ w 2 + b 2 ) \begin{aligned} y_2 &= y_1 * w_2 + b_2\\ &= ( x*w_1 + b_1) * w_2 + b_2\\ &=x * (w_1 * w_2) + (b_1 * w_2 + b_2) \end{aligned} y2=y1∗w2+b2=(x∗w1+b1)∗w2+b2=x∗(w1∗w2)+(b1∗w2+b2)
这本质上还是我们原来的模型 y = x ∗ w + b y = x*w + b y=x∗w+b,可以很容易的想到,无论经过多少层神经元,最后的模型依然是 y = x ∗ w + b y = x*w + b y=x∗w+b,所以模型表达力并不会有很大的提升。
现在终于可以揭晓答案了,原因是,我们的"神经网络"模型,其实仍然是个线性模型,因为无论多少层,其最终化简依然是线性模型!而线性模型的不能够表达非线性的部分
那我们怎样做才能将模型非线性话呢?对的,就是引入非线性的激活函数
早在1943年提出的MP模型 y = f ( x ∗ w + b ) y = f(x*w + b) y=f(x∗w+b) 中,就已经提出引入非线性函数 f f f:
而就是由于非线性函数的加入,使得输出 y y y不再是输入 x x x的线性组合,神经网络可以随着层数的增加提示表达力!
我们之前一定听说过, r e l u relu relu激活函数和 s i g m o i d sigmoid sigmoid激活函数,那他们这么有名,是具备了什么优秀的性质呢??
在今后的实践中,我们可以通过以上性质来寻找属于自己模型的激活函数!
tf.nn.sigmoid(x)
tf.math.tanh(x)
tf.nn.relu(x)
tf.nn.leaky_relu(x)
with tf.GradientTape() as tape:
#前向传播计算 y, y为预测结果
y = tf.matmul(x_train, w) + b
y = tf.nn.softmax(y) # <-------------------------在此处加入激活函数即可,没错,就加一句代码
# 计算损失函数
loss = (y - y_train)**2
loss = tf.reduce_mean(loss, axis=0)
加上激活函数,再去训练你的模型试试准确率,应该能达到 95 % 95\% 95%以上
https://www.desmos.com/calculator
注:在该网站还可以画分段函数,如绘制 r e l u relu relu函数:
{ x > 0 } x { x < 0 } 0 \{x>0\}\ x\\ \{x<0\}\ 0 {x>0} x{x<0} 0