首先,我希望你是Linux系用户,如果你是巨硬党,装一个VirtualBox吧,然后再装个ubuntu,由于我们只是入个门,对性能要求不高的。
机器学习相关的框架也很多,我这里选择了==keras== keras中文文档,后端采用的==tensorflow== 官方网站 。那么理所当然的,会用到python来开发,没有python经验也莫慌,影响并不大。
ubuntu自带python 我就不介绍怎么安装了吧?
先安装pip(我用的python2.7,后文统一)打开你的终端,输入这个:(我建议更换下apt-get为国内镜像,安装完pip后也更换为国内镜像吧)
sudo apt-get install python-pip python-dev
安装tensorflow和keras,matplotlib
还是打开终端,输入输入
pip install tensorflow
pip install matplotlib
pip install keras
安装完输入 python 然后import测试下
你也可以测试下tensorflow,下面是个标准hello world
import tensorflow as tfhello = tf.constant('Hello, TensorFlow!')sess = tf.Session()print(sess.run(hello))
你看,ubuntu下安装环境这么简单,我不知道你为什么不尝试下
我建议你先把CNN当作一个黑盒子,不要关心为什么,只关心结果。
这里借用了一个分辨X
和o
的例子来这里看原文,就是每次给你一张图,你需要判断它是否含有'X'或者'O'。并且假设必须两者选其一,不是'X'就是'O'。
下面看一下CNN是怎么分辨输入的图像是x还是o,如果需要你来编程分辨图像是x还是o,你会怎么做?可能你第一时间就想到了逐个像素点对比。但是,如果图片稍微有点变化呢?像是下面这个x,它不是标准的x,我们可以分辨它是x,但是对于计算机而言,它就只是一个二维矩阵,逐个像素点对比肯定是不行的。
CNN就是用于解决这类问题的,它不在意具体每个点的像素,而是通过一种叫卷积的手段,去提取图片的特征。
什么是特征? 特征就是我们用于区分两种输入是不是同一类的分辨点,像是这个XXOO的例子,如果要你描述X和O的区别,你会怎么思考?X是两条线交叉,O是封闭的中空的。。。
我们来看个小小的例子,如果下面两张图,需要分类出喜欢和不喜欢两类,那么你会提取什么作为区分的特征?(手动滑稽)
所以对于CNN而言,第一步就是提取特征,卷积就是提取猜测特征的神奇手段。而我们不需要指定特征,任凭它自己去猜测,就像上图,我们只需要告诉它,我们喜欢左边的,不喜欢右边的,然后它就去猜测,区分喜不喜欢的特征是黑丝,还是奶子呢?
假设,我们上面这个例子,CNN对于X
的猜测特征如上,现在要通过这些特征来分类。
计算机对于图像的认知是在矩阵上的,每一张图片有rgb二维矩阵(不考虑透明度)所以,一张图片,应该是3x高度x宽度
的矩阵。而我们这个例子就只有黑白,所以可以简单标记1为白,-1为黑。是个9x9的二维矩阵。
我们把上面的三个特征作为卷积核(我们这里是假设已经训练好了CNN,训练提出的特征就是上面三个,我们可以通过这三个特征去分类 X ),去和输入的图像做卷积(特征的匹配)。
看完上面的,估计你也能看出特征是如何去匹配输入的,这就是一个卷积的过程,具体的卷积计算过程如下(只展示部分):
把计算出的结果填入新的矩阵
其他部分也是相同的计算
最后,我们整张图用卷积核计算完成后:
三个特征都计算完成后:
不断地重复着上述过程,将卷积核(特征)和图中每一块进行卷积操作。最后我们会得到一个新的二维数组。其中的值,越接近为1表示对应位置的匹配度高,越是接近-1,表示对应位置与特征的反面更匹配,而值接近0的表示对应位置没有什么关联。
以上就是我们的卷积层,通过特征卷积,输出一个新的矩阵给下一层。
在图像经过以上的卷积层后,得到了一个新的矩阵,而矩阵的大小,则取决于卷积核的大小,和边缘的填充方式,总之,在这个XXOO的例子中,我们得到了7x7的矩阵。池化就是缩减图像尺寸和像素关联性的操作,只保留我们感兴趣(对于分类有意义)的信息。
常用的就是2x2的最大池。
看完上面的图,你应该知道池化是什么操作了。通常情况下,我们使用的都是2x2的最大池,就是在2x2的范围内,取最大值。因为最大池化(max-pooling)保留了每一个小块内的最大值,所以它相当于保留了这一块最佳的匹配结果(因为值越接近1表示匹配越好)。这也就意味着它不会具体关注窗口内到底是哪一个地方匹配了,而只关注是不是有某个地方匹配上了。这也就能够看出,CNN能够发现图像中是否具有某种特征,而不用在意到底在哪里具有这种特征。这也就能够帮助解决之前提到的计算机逐一像素匹配的死板做法。
同样的操作以后,我们就输出了3个4x4的矩阵。
全连接层一般是为了展平数据,输出最终分类结果前的归一化。 我们把上面得到的4x4矩阵再卷积 池化,得到2x2的矩阵
全连接就是这样子,展开数据,形成1xn的'条'型矩阵。
然后再把全连接层连接到输出层。之前我们就说过,这里的数值,越接近1表示关联度越大,然后我们根据这些关联度,分辨到底是O还是X.
看上图(圈圈里面的几个关键信息点),这里有个新的图像丢进我们的CNN了,根据卷积>池化>卷积>池化>全连接的步骤,我们得到了新的全连接数据,然后去跟我们的标准比对,得出相似度,可以看到,相似度是X的为0.92 所以,我们认为这个输入是X。
一个基本的卷积神经网络就是这样子的。回顾一下,它的结构:
Relu是常用的激活函数,所做的工作就是max(0,x),就是输入大于零,原样输出,小于零输出零,这里就不展开了。
感觉,这个mnist的手写数字,跟其他语言的helloworld一样了。我们这里来简单实现下。首先,我建议你先下载好数据集,keras的下载太慢了下载地址 下载好以后,按下面的位置放,你可能要先运行下程序,让他自己创建文件夹,不然,你就手动创建吧。
新建个python文件,test.py
然后输入下面的内容
#coding: utf-8from keras.datasets import mnistimport matplotlib.pyplot as plt# 加载数据(X_train, y_train), (X_test, y_test) = mnist.load_data()# 展示下第一张图plt.imshow(X_train[0], cmap=plt.get_cmap('PuBuGn_r'))plt.show()
运行后出来张图片,然后关掉就行,这里只是看看我们加载数据有没有问题。x_train
,x_test
是我们的图像矩阵数据,是28x28大小,然后有12500条吧好像。然后y_train
,y_test
都是标签数据,标明这张图代表是数字几。
#coding: utf-8#Simple CNNimport numpyfrom keras.datasets import mnistfrom keras.models import Sequentialfrom keras.layers import Densefrom keras.layers import Dropoutfrom keras.layers import Flattenfrom keras.layers.convolutional import Conv2Dfrom keras.layers.convolutional import MaxPooling2Dfrom keras.utils import np_utilsseed = 7numpy.random.seed(seed)#加载数据(X_train, y_train), (X_test, y_test) = mnist.load_data()# reshape to be [samples][channels][width][height]X_train = X_train.reshape(X_train.shape[0],28, 28,1).astype('float32')X_test = X_test.reshape(X_test.shape[0],28, 28,1).astype('float32')# normalize inputs from 0-255 to 0-1X_train = X_train / 255X_test = X_test / 255# one hot encode outputsy_train = np_utils.to_categorical(y_train)y_test = np_utils.to_categorical(y_test)num_classes = y_test.shape[1]# 简单的CNN模型def baseline_model(): # create model model = Sequential() #卷积层 model.add(Conv2D(32, (3, 3), padding='valid', input_shape=(28, 28,1), activation='relu')) #池化层 model.add(MaxPooling2D(pool_size=(2, 2))) #卷积 model.add(Conv2D(15, (3, 3), padding='valid' ,activation='relu')) #池化 model.add(MaxPooling2D(pool_size=(2, 2))) #全连接,然后输出 model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dense(num_classes, activation='softmax')) # Compile model model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) return model# build the modelmodel = baseline_model()# Fit the modelmodel.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=128, verbose=2)
代码也挺简单,因为keras也是封装的挺好的了。基本你看懂了前面的就没问题。
Epoch 1/103s - loss: 0.2791 - acc: 0.9203 - val_loss: 0.1420 - val_acc: 0.9579Epoch 2/103s - loss: 0.1122 - acc: 0.9679 - val_loss: 0.0992 - val_acc: 0.9699Epoch 3/103s - loss: 0.0724 - acc: 0.9790 - val_loss: 0.0784 - val_acc: 0.9745Epoch 4/103s - loss: 0.0509 - acc: 0.9853 - val_loss: 0.0774 - val_acc: 0.9773Epoch 5/103s - loss: 0.0366 - acc: 0.9898 - val_loss: 0.0626 - val_acc: 0.9794Epoch 6/103s - loss: 0.0265 - acc: 0.9930 - val_loss: 0.0639 - val_acc: 0.9797Epoch 7/103s - loss: 0.0185 - acc: 0.9956 - val_loss: 0.0611 - val_acc: 0.9811Epoch 8/103s - loss: 0.0150 - acc: 0.9967 - val_loss: 0.0616 - val_acc: 0.9816Epoch 9/104s - loss: 0.0107 - acc: 0.9980 - val_loss: 0.0604 - val_acc: 0.9821Epoch 10/104s - loss: 0.0073 - acc: 0.9988 - val_loss: 0.0611 - val_acc: 0.9819
然后你就能看到这些输出,acc就是准确率了,看后面的val_acc就行。
其他的参数那些,我建议你看看keras的文档。然后,入门就结束了。如果你感兴趣的话,就自己去摸索吧,后续我也可能会继续分享相关的内容。
联系客服