猫史档案馆


【优化方法】神经网络

用户:四九圣尊四九圣尊查看:182 回复:9 评论:2 创建时间:2018-12-07T20:46:10


假设我们的数据是这个样子的:center_image现在我们尝试通过尝试用这些数据预测(1,1,0)时的输出。仔细观察,不难发现output就是inputs的第一列。按照你可以按照我们之前教的线性回归来解决这个问题,最后会拟合出来一个【1,0,0】的参数向量。但今天我们要用另一种算法来解决这个问题。它就是神经网络:

 center_image

我画的这张图详细的解释了它的工作原理,乍一看跟线性回归完全一样。不过只是在输出时完全一样罢了,而且只要神经网络的层数增加(脑补一下),它就可以处理能力就比线性回归高多了,线性回归中一个数据只能对应一个权重,而神经网络却可以是多个。

 

那么我们如何优化这个模型呢?比如,我们要更新w00的权重,原理与之前一样,我们就要计算w00对L的偏导数,然后用w00-偏导数*学习率就完成了一次更新。也就是说,我们现在要计算:center_image。回溯到神经网络模型,如果真的手把手去推算这个导数的话,o my god我都无法想象,尤其是当神经网络层数巨大时,基本上没有可能对每个参数先在纸上进行求导再搬到程序上去。

 

这个时候怎么办呢?还记得我们之前讲的线性回归中均方误差损失函数的求导吗?我们是如何化简计算量的呢?链式求导法则啊:

所以我们就把center_image变成:center_image其中:center_image

这三个你们可以自己用手推导一下,这些导数都是一眼就可以看出来的那种,完全不用算。

我们对这些依次求导,最后乘在一起,就可以得出。因为这些相乘的导数是从后面求起的,所以这个算法叫反向传播。

代码:

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)

损失函数曲线:

center_image

当然,这里讲的只是神经网络的最基本应用,大家可以试着尝试增加一层:center_image更新权重的时候也就是多了一层导数。然后你对神经网络的理解会更加深刻。

 

 

 

 

 


回复

上一页第 1 页 / 共 1 页下一页
四九圣尊四九圣尊

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


评论


四九圣尊四九圣尊

多层神经网络对数据的模式有更高的见解,但是它也有很多问题,比如:center_imagecenter_image就很难分辨出(0,1,1)和(1,1,0)的区别。因为它对数据分类的标准不再是公式化的了,而是抽象到了一个更高的层次。

很显然神经网络把1的个数与结果联系在了一次,同时还有一些1的位置关系。但单层神经网络却只能考虑1的位置关系。

点赞0


评论


四九圣尊四九圣尊

如果想获得更快的收敛速度,可以把损失函数换成交叉熵损失。

点赞0


评论


霖雨暮风霖雨暮风

哇大佬

点赞0


评论


秋葵秋葵

找到了一个爆炸般的教程

如同一道闪电劈开了我的思绪

点赞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 

center_image

点赞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


评论

能放下C++的代码吗?


哲学喵哲学喵

握喵 是大佬!

点赞0


评论