深度学习:透过神经网络的内在灵活与柏拉图的哲学理念

以神经网络为基础的深度学习,它最大的作用就是让计算机能求解那些没有明确规则或定义的问题,例如你根本无法制定出一系列明确的规则或步骤去让计算机识别一幅图像中的内容是什么,人工智能最大的强项就是让计算机能处理那些模糊不清,几乎无法用明确的规则或步骤来描述的问题。

一个受过大量数据训练的神经网络,给定领域内的图像表示什么内容,此时它就像一个黑盒子,把数据从一端输入,然后结果自动从另一端输出,你根本不知道他内部的运行机制。如果我们只在乎得到正确的结果,那么无论神经网络的内部机理如何复杂,我们都无需关心。如果我们想知道神经网络是如何学习输入数据,并总结出某种特定规律来,那么我们现在能知道的,就是网络会不断的调整链路上权值。

由于神经网络模拟的是大脑思维方式,人的大脑有意识,那神经网络是否也有自己的”意识“呢?原来神经网络的工作流程如下: 数字图片 -> 神经网络 -> 数字 如果我们反其道而行之,给定一个数字,让神经网络把该数字对应的”图片“给画出来,那么我们就可以窥探神经网络是如何通过自己的”意识“来认识这个世界了,也就是我们把上面流程改为: 数字图片<-神经网络<-数字 通过上面的逆流程,我们就可以大概了解世界在神经网络中的样子。 我们已经知道,神经网络得出的结果是先把输入信号与链路权重做乘机后求和,然后在对求和结果应用激活函数,所的到的结果就是神经节点输出的信号。反过来,我们拿到最终输出结果后,先做激活函数的逆运算,得到信号与权重的乘机和,然后再除以链路权重还原回各个信号分量,将这些信号分量合成一幅图像,我们就可以得知,神经网络是如何看待这个世界的。

我们知道网络节点的激活函数如下:

要把里面的x解出来,我们就需要下面的公式:

在python中,它对应的代码为scipy.special.logit(),于是利用这个公式,我们用如下代码把结果反解出对应的图片,相应的实现代码如下:

import scipy.special
import numpy

class  NeuralNetWork:
    def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
        #初始化网络,设置输入层,中间层,和输出层节点数
        self.inodes = inputnodes
        self.hnodes = hiddennodes
        self.onodes = outputnodes

        #设置学习率
        self.lr = learningrate
        '''
        初始化权重矩阵,我们有两个权重矩阵,一个是wih表示输入层和中间层节点间链路权重形成的矩阵
        一个是who,表示中间层和输出层间链路权重形成的矩阵
        '''
        self.wih = numpy.random.rand(self.hnodes, self.inodes) - 0.5
        self.who = numpy.random.rand(self.onodes, self.hnodes) - 0.5

        self.activation_function = lambda x:scipy.special.expit(x)

        #设置激活函数的反函数
        self.inverse_activation_function = lambda x:scipy.special.logit(x)
        pass
    def  train(self, inputs_list, targets_list):
        #根据输入的训练数据更新节点链路权重
        '''
        把inputs_list, targets_list转换成numpy支持的二维矩阵
        .T表示做矩阵的转置
        '''
        inputs = numpy.array(inputs_list, ndmin=2).T
        targets = numpy.array(targets_list, ndmin=2).T
        #计算信号经过输入层后产生的信号量
        hidden_inputs = numpy.dot(self.wih, inputs)
        #中间层神经元对输入的信号做激活函数后得到输出信号
        hidden_outputs = self.activation_function(hidden_inputs)
        #输出层接收来自中间层的信号量
        final_inputs = numpy.dot(self.who, hidden_outputs)
        #输出层对信号量进行激活函数后得到最终输出信号
        final_outputs = self.activation_function(final_inputs)

        #计算误差
        output_errors = targets - final_outputs
        hidden_errors = numpy.dot(self.who.T, output_errors)
        #根据误差计算链路权重的更新量,然后把更新加到原来链路权重上
        self.who += self.lr * numpy.dot((output_errors * final_outputs *(1 - final_outputs)),
                                       numpy.transpose(hidden_outputs))
        self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1 - hidden_outputs)),
                                       numpy.transpose(inputs))

        pass
    def  query(self, inputs):
        #根据输入数据计算并输出答案
        #计算中间层从输入层接收到的信号量
        hidden_inputs = numpy.dot(self.wih, inputs)
        #计算中间层经过激活函数后形成的输出信号量
        hidden_outputs = self.activation_function(hidden_inputs)
        #计算最外层接收到的信号量
        final_inputs = numpy.dot(self.who, hidden_outputs)
        #计算最外层神经元经过激活函数后输出的信号量
        final_outputs = self.activation_function(final_inputs)
        return final_outputs
    def backQuery(self, targets_list):
         # 将结果向量转置以便反解出输入信号量
        final_outputs = numpy.array(targets_list, ndmin=2).T

        # 通过激活函数的反函数得到输出层的输入信号
        final_inputs = self.inverse_activation_function(final_outputs)

        # 获取中间层的输出信号
        hidden_outputs = numpy.dot(self.who.T, final_inputs)
        # 将信号量圆整到0.01和0.98之间
        hidden_outputs -= numpy.min(hidden_outputs)
        hidden_outputs /= numpy.max(hidden_outputs)
        hidden_outputs *= 0.98
        hidden_outputs += 0.01

        #通过激活函数的反函数计算中间层获得的输入信号量
        hidden_inputs = self.inverse_activation_function(hidden_outputs)

        # 计算输入层的输出信号量
        inputs = numpy.dot(self.wih.T, hidden_inputs)
        # 将信号量圆整到0.01和0.98之间
        inputs -= numpy.min(inputs)
        inputs /= numpy.max(inputs)
        inputs *= 0.98
        inputs += 0.01
        #input对应的就是输入神经网络的图片像素数组
        return inputs

上面代码跟以前不一样之处就在于多了一个backQuery函数,它接收结果向量,让后反解出向量对应的输入图片,有了上面神经网络后,我们先对其进行训练,得到相应的神经元链路权重:

#初始化网络
input_nodes = 784
hidden_nodes = 100
output_nodes = 10
learning_rate = 0.3
n = NeuralNetWork(input_nodes, hidden_nodes, output_nodes, learning_rate)
#读入训练数据
#open函数里的路径根据数据存储的路径来设定
training_data_file = open("/Users/chenyi/Documents/人工智能/mnist_train.csv")
trainning_data_list = training_data_file.readlines()
print(len(trainning_data_list))
training_data_file.close()
#加入epocs,设定网络的训练循环次数
epochs = 7
print("begin trainning")

for e in range(epochs):
    #把数据依靠','区分,并分别读入
    for record in trainning_data_list:
        all_values = record.split(',')
        inputs = (numpy.asfarray(all_values[1:]))/255.0 * 0.99 + 0.01
        #设置图片与数值的对应关系
        targets = numpy.zeros(output_nodes) + 0.01
        targets[int(all_values[0])] = 0.99
        n.train(inputs, targets)


print("trainning complete")

有了合适的链路权值后,我们构造一个结果向量,将它输入到网络中,让网络把它认为的向量对应的图像输出来:

label = 8
targets = numpy.zeros(output_nodes) + 0.01
targets[label] = 0.99
print(targets)
image_data = n.backQuery(targets)
#print(image_data.reshape(28,28))
matplotlib.pyplot.imshow(image_data.reshape(28,28), cmap="Greys", interpolation="None")

上面代码构造了一个数字8对应的结果向量,然后传入神经网络看看网络眼中的数字8是什么样子的,上面代码执行后结果如下:

没错,上面模糊一片的图案就是神经网络对数组8的理解,我们慢慢观察黑色部分,发觉它确实跟数字8有点像。这个图案让我想起了两千年前古希腊哲学家柏拉图提出一个叫”理型“的哲学概念,它的意思是说,每一个种类的事物,无论其外形如何变幻,他们本身都包含着一种超越时空,永恒不变的抽象属性。举个例子,给一个孩子看一只黑马的图片,然后让他看一只白马的图片,他很容易能认出那是马,也就是说不管黑马白马的外形差异如何,两只马都具备相同的理型叫做”马“,人正是因为感受到马的”理型“,所以不管马的形态如何变幻,人总能认出它是马来,也就是说所有的马都具备同一种抽象的超越时空,永恒不变的性质,正是这个性质将它与其他事物区分开来。

道可道,非常道。理型的概念就是”道可道“中的第一个道,也就是永恒不变的规律,通常情况下,”道“是很难用语言或某种显著方式进行表达的。神经网络通过计算大量的手写数字图片,通过计算抽取出了这些同一类数字图片的共性,这个共性其实就是柏拉图所说的理型,也就是所有手写的数字”8“,都蕴含着某种不变的性质,神经网络就是把这个性质抽取出来的方式,上面那张模糊的图案,可以认为是所有手写数字8的理型,网络读取的图片数量越大,其对理型的把握就越准确。

如此一来”非常道“似乎就不成立了,神经网络的结构以及链路上的权重,就可以用来对”道“进行描述,或者说一切手写数字的”理型“可以用现在我们训练的神经网络来描述。

以神经网络为基础的深度学习模仿人的意识,在一定程度上也跟人的思维哲学有了交互之处,这就是技术发展与人文思想的交相辉映吧。至此我们对神经网络的基本原理说明就告一段落,从下一章开始,我们进入神经网络的实际应用层面。

本文分享自微信公众号 - Coding迪斯尼(gh_c9f933e7765d)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-06-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器学习、深度学习

人群密度估计--Generating High-Quality Crowd Density Maps using Contextual Pyramid CNNs

Generating High-Quality Crowd Density Maps using Contextual Pyramid CNNs ICCV2...

33850
来自专栏CVer

[计算机视觉论文速递] 2018-05-22

Amusi 将日常整理的论文都会同步发布到 daily-paper-computer-vision 上。名字有点露骨,还请见谅。喜欢的童鞋,欢迎star、for...

10820
来自专栏目标检测和深度学习

干货 | 目标检测入门,看这篇就够了(下)

作者 | 李家丞( 同济大学数学系本科在读,现格灵深瞳算法部实习生) 近年来,深度学习模型逐渐取代传统机器视觉方法而成为目标检测领域的主流算法,本系列文章将回...

61480
来自专栏CVer

[计算机视觉论文速递] 2018-03-09

通知:这篇推文有19篇论文速递信息,涉及图像分类、目标检测、目标分割、超分辨率SR、姿态估计、行人重识别Re-ID等方向 [1]《A Deep Learning...

386100
来自专栏机器学习AI算法工程

谱聚类、Chameleon聚类、PCCA、SOM、Affinity Propagation

层次聚类和K-means聚类,可以说是聚类算法里面最基本的两种方法(wiki的cluster analysis页面都把它们排前两位)。这次要探讨的,则是两个相...

45530
来自专栏机器学习AI算法工程

Python机器学习从原理到实践(2):数据拟合与广义线性回归

机器学习中的预测问题通常分为2类:回归与分类。 简单的说回归就是预测数值,而分类是给数据打上标签归类。 本文讲述如何用Python进行基本的数据拟合,以及如何对...

38180
来自专栏量化投资与机器学习

【原创精品】使用R语言gbm包实现梯度提升算法

原创推文预告(绿色为已发布,点击标题即可阅读) ● 随机森林在因子选择上的应用基于Matlab ● 择时策略:在一天的何时进行交易 ● 主题模型 - LD...

58370
来自专栏汪毅雄的专栏

机器学习之回归原理详述(一)

本文用了从数学层面和代码层面,再结合一些通俗易懂的例子,详细地描述了回归主要涉及的原理和知识,希望对于机器学习的初学者或者有兴趣研究模型具体实现的同学带来一点帮...

1.5K30
来自专栏一心无二用,本人只专注于基础图像算法的实现与优化。

使用局部标准差实现图像的局部对比度增强算法。

      图像的对比度增强算法在很多场合都有着重要的应用,特别是在医学图像上,这是因为在众多疾病的诊断中,医学图像的视觉检查时很有必要的。而医学图像由于本身及...

41490
来自专栏机器学习和数学

[有意思的数学] 傅里叶变换和卷积与图像滤波的关系 (2)

昨天简单介绍了Fourier变换和卷积的概念,有了一个基本的认识之后,再看图像滤波,就不会觉得那么莫名其妙了。图像滤波这其实也是个大坑,里面涉及的东西很多,想通...

51360

扫码关注云+社区

领取腾讯云代金券