用户:四九圣尊查看:2 回复:9 评论:2 创建时间:2018-12-07T20:46:10
假设我们的数据是这个样子的:现在我们尝试通过尝试用这些数据预测(1,1,0)时的输出。仔细观察,不难发现output就是inputs的第一列。按照你可以按照我们之前教的线性回归来解决这个问题,最后会拟合出来一个【1,0,0】的参数向量。但今天我们要用另一种算法来解决这个问题。它就是神经网络:
我画的这张图详细的解释了它的工作原理,乍一看跟线性回归完全一样。不过只是在输出时完全一样罢了,而且只要神经网络的层数增加(脑补一下),它就可以处理能力就比线性回归高多了,线性回归中一个数据只能对应一个权重,而神经网络却可以是多个。
那么我们如何优化这个模型呢?比如,我们要更新w00的权重,原理与之前一样,我们就要计算w00对L的偏导数,然后用w00-偏导数*学习率就完成了一次更新。也就是说,我们现在要计算:。回溯到神经网络模型,如果真的手把手去推算这个导数的话,o my god我都无法想象,尤其是当神经网络层数巨大时,基本上没有可能对每个参数先在纸上进行求导再搬到程序上去。
这个时候怎么办呢?还记得我们之前讲的线性回归中均方误差损失函数的求导吗?我们是如何化简计算量的呢?链式求导法则啊:
所以我们就把变成:
其中:
这三个你们可以自己用手推导一下,这些导数都是一眼就可以看出来的那种,完全不用算。
我们对这些依次求导,最后乘在一起,就可以得出。因为这些相乘的导数是从后面求起的,所以这个算法叫反向传播。
代码:
import numpy as np
from matplotlib import pyplot as plt
data = np.array([[1,0,1],
[0,0,1],
[1,1,1],
[0,0,1]])
label = np.array([[1,0,1,0]]).T
np.random.seed(1)
def sigmod(x,der=False):
result = 1/(1+np.exp(-x))
if not der:
return result
else:
return x*(1-x)
lr = 0.01
l0 = 2*np.random.random((3,1))-1
print(data.shape,label.shape,l0.shape)
loss_sum = []
for i in range(100000):
out0 = sigmod(data.dot(l0))
loss = np.sum((out0-label)**2)
loss_sum.append(loss)
l0 -= np.dot(data.T,-(label-out0)*sigmod(out0,der=True))*lr
plt.plot(loss_sum)
plt.show()
result = []
for i in sigmod(data.dot(l0)):
if i > 0.5:
result.append(1)
else:
result.append(0)
print(result)
损失函数曲线:
当然,这里讲的只是神经网络的最基本应用,大家可以试着尝试增加一层:更新权重的时候也就是多了一层导数。然后你对神经网络的理解会更加深刻。
import numpy as np
from matplotlib import pyplot as plt
import tqdm
data = np.array([[1,0,1],
[0,0,1],
[1,1,1],
[0,1,1],
[1,1,0]])
label = np.array([[1,0,1,0,1]]).T
np.random.seed(1)
def sigmod(x,der=False):
result = 1/(1+np.exp(-x))
if not der:
return result
else:
return x*(1-x)
lr = 0.1
l0 = 2*np.random.random((3,3))-1
l1 = 2*np.random.random((3,1))-1
for i in tqdm.tqdm(range(100000)):
out0 = sigmod(data.dot(l0))
out1 = sigmod(out0.dot(l1))
loss = np.sum((out1 - label) ** 2)
l1_c = np.dot(out0.T, (label - out1) * sigmod(out1, der=True))
l1 += l1_c*lr
l0 += np.dot(data.T,l1_c.T*sigmod(out0,der=True))*lr
print(out1)
2层神经网络
点赞0
评论
多层神经网络对数据的模式有更高的见解,但是它也有很多问题,比如:就很难分辨出(0,1,1)和(1,1,0)的区别。因为它对数据分类的标准不再是公式化的了,而是抽象到了一个更高的层次。
很显然神经网络把1的个数与结果联系在了一次,同时还有一些1的位置关系。但单层神经网络却只能考虑1的位置关系。
点赞0
评论
帮你整理补一下运行效果,先是代码
import numpy as np
from matplotlib import pyplot as plt
import tqdm
data = np.array([[1,0,1],
[0,0,1],
[1,1,1],
[0,1,1],
[1,1,0]])
label = np.array([[1,0,1,0,1]]).T
np.random.seed(1)
def sigmod(x,der=False):
result = 1/(1+np.exp(-x))
if not der:
return result
else:
return x*(1-x)
lr = 0.1
l0 = 2*np.random.random((3,3))-1
l1 = 2*np.random.random((3,1))-1
for i in tqdm.tqdm(range(100000)):
out0 = sigmod(data.dot(l0))
out1 = sigmod(out0.dot(l1))
loss = np.sum((out1 - label) ** 2)
l1_c = np.dot(out0.T, (label - out1) * sigmod(out1, der=True))
l1 += l1_c*lr
l0 += np.dot(data.T,l1_c.T*sigmod(out0,der=True))*lr
print(out1
点赞0
评论
import numpy as np
from matplotlib import pyplot as plt
import tqdm
data = np.array([[0,0,1],
[0,1,1],
[1,0,1],
[1,1,1]])
label = np.array([[0],
[1],
[1],
[0]])
np.random.seed(1)
layer0 = 2*np.random.random((3,4))-1
l0_b = 1
layer1 = 2*np.random.random((4,1))-1
l1_b = 1
def sigmod(x,deriv=False):
output = 1/(1+np.exp(-x))
if deriv:
return output*(1-output)
else:
return output
lr = 1
for i in tqdm.tqdm(range(100000)):
out1 = sigmod(data.dot(layer0)+l0_b)
out2 = sigmod(out1.dot(layer1)+l1_b)
layer1_error = (label - out2)
layer1_deriv = layer1_error*sigmod(out2,True)
layer0_error = layer1_deriv.dot(layer1.T)
layer0_deriv = layer0_error*sigmod(out1,True)
layer1 += out1.T.dot(layer1_deriv)*lr
l1_b += layer1_deriv
layer0 += data.T.dot(layer0_deriv)*lr
l0_b += layer0_deriv
print(out2)
之前的两层有个地方写错了,忘记加乘l1了,改了一下现在,然后加了一个偏置单元
点赞0
评论
用这个算法分类之前的鸢尾花:
import numpy as np
from matplotlib import pyplot as plt
import tqdm
from sklearn.datasets import load_iris
data_f = load_iris()
target = data_f.target.tolist()
data = data_f.data
data = [x.tolist() for x in data]
del data[90:150]
del target[90:150]
for i in range(len(data)):
del data[i][2:4]
data = np.array(data)
label = np.array([target]).T
np.random.seed(1)
layer0 = 2*np.random.random((2,30))-1
l0_b = 1
layer1 = 2*np.random.random((30,1))-1
l1_b = 1
def sigmod(x,deriv=False):
output = 1/(1+np.exp(-x))
if deriv:
return output*(1-output)
else:
return output
lr = 0.01
for i in range(100000):
out1 = sigmod(data.dot(layer0)+l0_b)
out2 = sigmod(out1.dot(layer1)+l1_b)
layer1_error = (label - out2)
layer1_deriv = layer1_error*sigmod(out2,True)
layer0_error = layer1_deriv.dot(layer1.T)
layer0_deriv = layer0_error*sigmod(out1,True)
layer1 += out1.T.dot(layer1_deriv)*lr
l1_b += layer1_deriv
layer0 += data.T.dot(layer0_deriv)*lr
l0_b += layer0_deriv
print("Loss:" + str(np.mean(layer1_error)) + " 第" + str(i) + "/100000轮")
print(out2)
点赞0
评论