学习资料Convolutional Neural Network with js
假设现在我们的network的input是一张6\times6的Image,如果是黑白的,一个pixel就只需要用一个value去描述它,1就代表有涂墨水,0就代表没有涂到墨水。那在convolution layer里面,它由一组的filter,(其中每一个filter其实就等同于是fully connect layer里面的一个neuron),每一个filter其实就是一个matrix(3 \times 3),这每个filter里面的参数(matrix里面每一个element值)就是network的parameter(这些parameter是要学习出来的,并不是需要人去设计的)。
每个filter如果是3 \times 3的detects意味着它就是再侦测一个3 \times 3 的pattern(看3 \times 3的一个范围)。在侦测pattern的时候不看整张image,只看一个3 \times 3的范围内就可以决定有没有某一个pattern的出现。这个就是我们考虑的第一个Property。
经过这件事情以后,本来是6 *6的matrix,经过convolution process就得到4 *4的matrix。如果你看filter的值,斜对角的值是1,1,1。所以它的工作就是detection有没有1,1,1(连续左上到右下的出现在这个image里面)。比如说:出现在这里(如图所示蓝色的直线),所以这个filter就会告诉你:左上跟左下出现最大的值
就代表说这个filter要侦测的pattern,出现在这张image的左上角和左下角,这件事情就考虑了propetry2。同一个pattern出现在了左上角的位置跟左下角的位置,我们就可以用filter 1侦测出来,并不需要不同的filter来做这件事。
在做convolution的话,就是将filter的9个值和image的9个值做内积(不是把每一个channel分开来算,而是合在一起来算,一个filter就考虑了不同颜色所代表的channel)
convolution就是fully connected layer把一些weight拿掉了。经过convolution的output其实就是一个hidden layer的neural的output。如果把这两个link在一起的话,convolution就是fully connected拿掉一些weight的结果。
在fully connected中,一个neural应该是连接在所有的input(有36个pixel当做input,这个neuron应连接在36个input上),但是现在只连接了9个input(detain一个pattern,不需要看整张image,看9个input就好),这样做就是用了比较少的参数了。
将stride=1(移动一格)做内积得到另外一个值-1,假设这个-1是另外一个neural的output,这个neural连接到input的(2,3,4,8,9,10,14,15,16),同样的weight代表同样的颜色。在9个matrix
当我们做这件事情就意味说:这两个neuron本来就在fully connect里面这两个neural本来是有自己的weight,当我们在做convolution时,首先把每一个neural连接的wight减少,强迫这两个neural共用一个weight。这件事就叫做shared weight,当我们做这件事情的时候,我们用的这个参数就比原来的更少。
这件事可以repeat很多次,通过一个convolution + max pooling就得到新的 image。它是一个比较小的image,可以把这个小的image,做同样的事情,再次通过convolution + max pooling,将得到一个更小的image。
这边有一个问题:第一次有25个filter,得到25个feature map,第二个也是由25个filter,那将其做完是不是要得到的feature map。其实不是这样的!25^2
假设第一层filter有2个,第二层的filter在考虑这个imput时是会考虑深度的,并不是每个channel分开考虑,而是一次考虑所有的channel。所以convolution有多少个filter,output就有多少个filter(convolution有25个filter,output就有25个filter。只不过,这25个filter都是一个立方体)
flatten就是feature map拉直,拉直之后就可以丢到fully connected feedforward netwwork,然后就结束了。
唯一要改的是:network structure和input format,本来在DNN中input是一个vector,现在是CNN的话,会考虑 input image的几何空间的,所以不能给它一个vector。应该input一个tensor(高维的vector)。为什么要给三维的vector?因为image的长宽高各是一维,若是彩色的话就是第三维。所以要给三维的tensor
model.add(Convolution2D( 25, 3, 3)
25代表有25个filter,3 *3代表filter是一个3 *3的matrix
Input_shape=(28,28,1)
假设我要做手写数字辨识,input是28 *28的image,每个pixel都是单一颜色。所以input_shape是(1,28,28)。如果是黑白图为1(blacj/white),如果是彩色的图时为3(每个pixel用三个值来表述)。
MaxPooling2D(( 2, 2 ))
2,2表示把2*2的feature map里面的pixel拿出来,选择max value
然后在做一次convolution,假设我在这选50个filter,每一个filter是3 *3时,那么现在的channel就是50。13 *13的image通过3 *3的filter,就成11 *11,然后通过2 *2的Max Pooling,变成了50 *5 *5
在第一个convolution layer里面,每一个filter有9个参数,在第二个convolution layer里面,虽然每一个filter都是3 *3,但不是3 *3个参数,因为它input channel 是25个,所以它的参数是3 *3 *25(225)。
import numpy as np import keras # 导入Keras库 from keras.models import Sequential # 导入Keras层 from keras.layers import Dense,Dropout,Activation,Convolution2D,MaxPooling2D,Flatten # 导入Keras优化器 from keras.optimizers import SGD,Adam # 导入Keras数据集 from keras.utils import to_categorical from keras.datasets import mnist print(np.__version__) # 1.23.5 print(keras.__version__) # 2.13.1 # 加载mnist数据集,将训练集和测试集分别赋值给x_train,y_train,x_test,y_test (x_train, y_train), (x_test, y_test) = mnist.load_data() # 将训练集和测试集的形状转换为(60000,28,28,1)和(10000,28,28,1) x_train = x_train.reshape(60000,28,28,1) x_test = x_test.reshape(10000,28,28,1) # 将训练集和测试集的标签转换为one-hot编码 y_train = to_categorical(y_train,10) y_test = to_categorical(y_test,10) # x_train=x_train/255 # x_test=x_test/255
# 定义一个模型 model2 = Sequential() # model2.add(Dense(input_dim=28*28, units=633,activation='relu')) # 添加一个卷积层,输入维度为28*28,输出维度为633,激活函数为relu model2.add(Convolution2D(25,3,3,input_shape=(28,28,1))) # 添加一个池化层,池化核为2*2 model2.add(MaxPooling2D((2,2))) # 添加一个Flatten层,将输入的维度转换为(None,7*7*633) model2.add(Flatten()) # 添加一个全连接层,输出维度为100,激活函数为relu model2.add(Dense(units=100,activation="relu")) # 添加一个全连接层,输出维度为100,激活函数为relu model2.add(Dense(units=100,activation="relu")) # 添加10个全连接层,输出维度为633,激活函数为relu # for i in range(10): # model2.add(Dense(units=633,activation="relu")) # 添加一个全连接层,输出维度为10,激活函数为softmax model2.add(Dense(units=10,activation="softmax")) # model2.compile(loss="categorical_crossentropy",optimizer=SGD(learning_rate=0.1), metrics=['accuracy']) # 编译模型,损失函数为categorical_crossentropy,优化器为SGD,学习率为0.1,指标为accuracy model2.compile(loss="categorical_crossentropy",optimizer="adam", metrics=['accuracy']) # 训练模型,batch_size为100,epochs为20 model2.fit(x_train, y_train, batch_size=100, epochs=20) # 计算模型的训练精度 restult = model2.evaluate(x_train, y_train,batch_size=10000) print("Train Acc:",restult[1]) # 计算模型的测试精度 restult = model2.evaluate(x_test, y_test) print("Test Acc:",restult[1])