You keep using that word, but I don't think it means what you think it means.
就像上面说的这句话,每当看见“神经网络”这个词的时候,我都是懵逼的,到底啥是神经网络?和深度学习有啥关系?你瞅啥?
懵逼史
作为一个长期进行业务开发的我,在机缘巧合下开始接触算法。刚开始是看各种业务场景如何运用机器学习算法分析和预测的文章,看完之后觉得作者非常牛逼,但是自己是懵逼的。感觉就像耍猴一样,还没学会站着走,就要玩穿火圈了。为了穿火圈,开始了一枚程序猿走野路子学算法的奇葩。就像机器学习里面提到的无监督学习,监督学习,增强学习一样,人类学习任何知识的过程,站在上帝视角来看,人类更像在使用增强学习不断修正对世界的认知模型。还是有一些漏洞,人与人之前的交互学习算无监督学习,监督学习还是算增强学习?第一个人类,用视觉认知这个世界,开始沉淀知识,到现在的人类,已经有一个非常强大的知识库。我们可以直接获得这些知识,不断迭代,修正人类对世界的认知模型。看完这段话,结论还是两个字,“懵逼”。为了稍微不心慌一点,我们可以先从1+1=2开始从新认识这个世界。
神经元
一个神经元通常具有多个树突,主要用来接受输入的信息(Input);而轴突只有一条(Algorithm),轴突尾端有许多轴突末梢可以给其他多个神经元传递信息(Output)。轴突末梢跟其他神经元的树突产生连接(Connection),从而传递信号。举个例子,人类的眼睛可以收集视觉信息,然后刺激产生生物电磁脉冲把信息导向神经元的树突,最终输出眼睛看见的物体认知结果。
简化版
详细版
神经网络
神经网络描述如下:
上图中每个圆圈都是一个神经元(Neuron),每条线表示神经元之间的连接(Connection)。我们可以看到,上面的神经元被分成了多层(Layer),层与层之间的神经元有连接,而层内之间的神经元没有连接。最左边的层叫做输入层(Input Layer),这层负责接收输入数据;最右边的层叫输出层(Output Layer),我们可以从这层获取神经网络输出数据。输入层和输出层之间的层叫做隐藏层(Hidden Layer)。隐藏层大于2的叫深度神经网络,功能更强大。简单来说就是用深度换广度,但是需要更多的样本数据来训练。
感知器
感知器也叫单层神经网络(单个运算层),就是很简单的一种神经网络,1+1=2这种。感知器结构如图:
概念模型:
- 输入及权重:一个感知器可以接收多个输入,每个输入上有一个权值,此外还有一个偏置项bias=x0*w0
- 加权求和(Weighted Sum)
- 激活函数(Activator):上图里面是一个阶跃函数(Step Function)
- 输出(Output)
训练时的数学模型(数学公式插件不好使啊):
-
加权求和:
-
阶跃函数:
-
输出:
-
训练模型
-
权重
-
偏置项:
- 学习速率:艾塔符号
-
核心代码(Python)
加权求和
reduce(lambda a, b: a + b,
map(lambda (x, w): x * w, zip(input_vecs, self.weights))
, 0.0) + self.bias
阶跃函数
def step_f(z):
return 1 if z > 0 else 0
输出
self.activator(
reduce(lambda a, b: a + b,
map(lambda (x, w): x * w, zip(input_vecs, self.weights))
, 0.0) + self.bias
)
训练模型-权重
self.weights = map(lambda (x, w): w + rate * delta * x, zip(input_vec, self.weights))
训练模型-偏置项
self.bias += rate * delta
模拟布尔运算代码(AND、OR、XOR)
class Perceptron(object):
def __init__(self, features_num, activator):
self.features_num = features_num
self.weights = [0.0 for i in range(features_num)]
self.activator = activator
self.bias = 0.0
def __str__(self):
return 'weights:%s \n bias:%s \n' % (self.weights, self.bias)
def predict(self, input_vecs):
return self.activator(
reduce(lambda a, b: a + b,
map(lambda (x, w): x * w, zip(input_vecs, self.weights))
, 0.0) + self.bias
)
def train(self, input_vecs, labels, iteration, rate):
for i in range(iteration):
samples = zip(input_vecs, labels)
for (input_vec, label) in samples:
output = self.predict(input_vec)
self.update_weights(input_vec, label, output, rate)
def update_weights(self, input_vec, label, output, rate):
delta = label - output
self.weights = map(lambda (x, w): w + rate * delta * x, zip(input_vec, self.weights))
self.bias += rate * delta
def step_f(z):
return 1 if z > 0 else 0
def get_training_ds(operator):
input_vecs = [[1, 0], [1, 1], [0, 0], [0, 1]]
if operator == 'AND':
labels = [0, 1, 0, 0]
if operator == 'OR':
labels = [1, 1, 0, 1]
if operator == 'XOR':
labels = [1, 0, 0, 1]
return input_vecs, labels
if __name__ == '__main__':
input_vecs, labels = get_training_ds('AND')
and_perceptron = Perceptron(2, step_f)
and_perceptron.train(input_vecs, labels, 5, 0.2)
print and_perceptron
print '0 and 1 -> %s \n' % and_perceptron.predict([0, 1])
print '1 and 0 -> %s \n' % and_perceptron.predict([1, 0])
print '1 and 1 -> %s \n' % and_perceptron.predict([1, 1])
print '0 and 0 -> %s \n' % and_perceptron.predict([0, 0])
input_vecs, labels = get_training_ds('OR')
or_perceptron = Perceptron(2, step_f)
or_perceptron.train(input_vecs, labels, 5, 0.2)
print or_perceptron
print '0 and 1 -> %s \n' % or_perceptron.predict([0, 1])
print '1 and 0 -> %s \n' % or_perceptron.predict([1, 0])
print '1 and 1 -> %s \n' % or_perceptron.predict([1, 1])
print '0 and 0 -> %s \n' % or_perceptron.predict([0, 0])
input_vecs, labels = get_training_ds('XOR')
xor_perceptron = Perceptron(2, step_f)
xor_perceptron.train(input_vecs, labels, 5, 0.1)
print xor_perceptron
print '0 and 1 -> %s \n' % xor_perceptron.predict([0, 1])
print '1 and 0 -> %s \n' % xor_perceptron.predict([1, 0])
print '1 and 1 -> %s \n' % xor_perceptron.predict([1, 1])
print '0 and 0 -> %s \n' % xor_perceptron.predict([0, 0])
输出结果(XOR搞不定,因为单层神经网络只能搞定如下这种一条直线的分类):
weights:[0.4, 0.2]
bias:-0.4
0 and 1 -> 0
1 and 0 -> 0
1 and 1 -> 1
0 and 0 -> 0
weights:[0.2, 0.2]
bias:0.0
0 and 1 -> 1
1 and 0 -> 1
1 and 1 -> 1
0 and 0 -> 0
weights:[-0.1, 0.0]
bias:0.1
0 and 1 -> 1
1 and 0 -> 0
1 and 1 -> 0
0 and 0 -> 1
深度神经网络
神经元更多,2+Hidden Layers,激活函数(阶跃、Sigmoid、Tanh)