抽象的艺术 - 感知器

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)

抽象的艺术 - 感知器

上一篇:视频聊天室源码,按住对话框右滑显示删除


下一篇:今日内容