如何使用Keras训练自己的CNN【程序+笔记1】

一. 理解keras的配置+图片转换为矩阵

在搭建自己的网络之前,我们首先看一下keras.json  这一个文件。

1. 理解keras.json 文件

    当你导入keras库的时候,keras会产生一个keras.json 文件,打开它(如果找不到就在安装keras库里面搜索)

    打开之后是这样的:

{
    "epsilon": 1e-07,
    "floatx": "float32",
    "image_data_format": "channels_last",
    "backend": "tensorflow"
}

在里面,你可以看到四个重要的参数,我们一一说一下它的作用。

(1) epsilon: 防止作除法时,分母为0

(2)float32:定义精度

(3) backend:keras库使用tensorflow作为后端,你也可以使用theano作为后端,将其改为theano

(4) image_data_format: 这个非常重要,这个值有两个类型:channels_last 和channels_first

                                           在opencv中,我们知道也是(rows,columns,channels), 即channels_last类型。

                                           但是在theano的设定中是channel_first的设定。


2. 导入图片, 并将图片转换为矩阵处理(有很多程序,不过一劳永逸,保存为package)

将一个project保存为这样的形式,我们一步一步往里面加东西

|--- pyimagesearch
| |--- __init__.py
| |--- datasets
| | |--- __init__.py
| | |--- SimpleDatasetLoader.py   #根据类名大写
| |--- preprocessing
| | |--- __init__.py
| | |--- ImageToArrayPreprocessor.py  #根据类名大写
| | |--- SimplePreprocessor.py

关于init文件,都是空的,不过必须要建立起作用。

第一步,打开preprocessing文件夹里面的

ImageToArrayPreprocessor.py

添加程序如下,这一步主要是将图片转换成矩阵的形式:

from keras.preprocessing.image import img_to_array

class ImageToArrayPreprocessor:
    def __init__(self,dataFormat=None):
        self.dataFormat=dataFormat

    def preprocess(self,image):
        return img_to_array(image,data_format=self.dataFormat)

第二步,打开preprocessing文件夹里面的

SimplePreprocessor.py

添加程序如下,这一步主要是可以rezise图片到你自己想要的大小

# -*- coding: utf-8 -*-

import cv2
class  SimplePreprocessor:
     def  __init__( self, width, height, inter=cv2.INTER_AREA):
         self.width=width
         self.height=height
         self.inter=inter
        
     def  preprocess( self, image):
         return cv2.resize(image,( self.width, self.height),  interpolation= self.inter)

第三步,打开datasets里面的

SimpleDatasetLoader.py  

添加程序如下,这一步骤主要作用为导入你需要的图片

# -*- coding: utf-8 -*-
import numpy  as np
import cv2
import os

class  SimpleDatasetLoader:
     def  __init__( self, preprocessors= None):
         self.preprocessors = preprocessors
        
         if  self.preprocessors is  None:
             self.preprocessors=[]

     def  load( self, imagePaths, verbose=- 1):
        data=[]
        labels=[]
         for (i, imagePath) in  enumerate (imagePaths):
            image =cv2.imread(imagePath)
            label=imagePath.split(os.path.sep)[- 2]  #这个非常重要,文件夹建立名称为类名,为label

             if  self.preprocessors is not  None:
                 for p in  self.preprocessors:
                    image=p.preprocess(image)
                    
            data.append(image)
            labels.append(label)
             if verbose > 0 and i> 0 and (i+ 1)%verbose== 0:
                 print( '[INFO] processed {}/{}'.format(i+ 1,
                       len(imagePaths)))
         return (np.array(data),np.array(labels))


完成了以上三个步骤,基本的图片输入和转换需要的程序就已经写好了,我们可以看一下主要的步骤

1. 导入图片

2. 改变图片大小

3. 选择通道维度

4. 输出矩阵


二. 建立一个简单的卷积网络 ShallowNet

第四步,先从简单的网络开始建立,我们建立我们的package如图所示,该conv文件集里面的shallownet为我们要做的网络:

--- pyimagesearch
| |--- __init__.py
| |--- datasets
| |--- nn
| | |--- __init__.py
...
| | |--- conv
| | | |--- __init__.py
| | | |--- ShallowNet.py
| |--- preprocessing

打开其文件,输入程序如下所示,为一个简单的卷积网络,后面我们会讲更加复杂的,不过现在来一点自己建立网络的满足感:

from keras.models  import Sequential
from keras.layers.convolutional  import  Conv2D
from keras.layers.core  import  Activation
from keras.layers.core  import Dense
from keras.layers.core  import Flatten
from keras  import backend  as K

class  ShallowNet:
     def  build( width, height, depth, classes):
        model=Sequential()
        inputShape=(height,width,depth)
         if K.image_data_format()== 'channel_first':
            inputShape=(depth,height,width)    #我们之前讲的通道点

        model.add(Conv2D( 32,( 3, 3), padding= 'same', input_shape=inputShape, activation= 'relu'))
        model.add(Flatten())
        model.add(Dense(classes, activation= 'softmax')) #根据自己的类别修改,类似于二分类为sigmoid
         return model

最后一步,建立一个新的文件导入我们的图片以及开始训练

取名可以叫做shallownet_animals.py

程序如下:

from sklearn.preprocessing  import LabelBinarizer
from sklearn.model_selection  import train_test_split
from sklearn.metrics  import classification_report
from pyimagesearch.preprocessing  import ImageToArrayPreprocessor
from pyimagesearch.preprocessing  import SimplePreprocessor
from pyimagesearch.datasets  import SimpleDatasetLoader
from pyimagesearch.nn.conv  import ShallowNet
from keras.optimizers  import SGD
from imutils  import paths
import matplotlib.pyplot  as plt
import numpy  as np
import argparse

ap=argparse.ArgumentParser()
ap.add_argument( '-d', '--dataset', required= True, help= 'path to the input dataset')
args= vars(ap.parse_args())

print( '[INFO] loading images...')
imagePaths= list(paths.list_images(args[ 'dataset']))

sp=SimplePreprocessor.SimplePreprocessor( 32, 32)
iap=ImageToArrayPreprocessor.ImageToArrayPreprocessor()
sdl=SimpleDatasetLoader.SimpleDatasetLoader( preprocessors=[sp,iap])
(data,labels)=sdl.load(imagePaths, verbose= 500)
data=data.astype( 'float')/ 255.0

(train_x,test_x,train_y,test_y)=train_test_split(data,labels, test_size= 0.25, random_state= 42)
train_y=LabelBinarizer().fit_transform(train_y)
test_y=LabelBinarizer().fit_transform(test_y)
#print(train_x.shape)
#print(train_y)
print( '[INFO] compiling models...')
opt=SGD( lr= 0.005)
model=ShallowNet.ShallowNet.build( width= 32, height= 32, depth= 3, classes= 1)
model.compile( loss= 'binary_crossentropy', optimizer=opt, metrics=[ 'accuracy']) #多分类的话为categorical_crossentropy


print( '[INFO] training network...')

H=model.fit(train_x,train_y, validation_data=(test_x,test_y), batch_size= 32, epochs= 100, verbose= 1)

print( '[INFO] evaliatiing model...')
predictions=model.predict(test_x, batch_size= 32)
print(classification_report(test_y.argmax( axis= 1),predictions.argmax( axis= 1), target_names=[ 'cat', 'dog']))


plt.style.use( "ggplot")
plt.figure()
plt.plot(np.arange( 0100), H.history[ "loss"],  label= "train_loss")
plt.plot(np.arange( 0100), H.history[ "val_loss"],  label= "val_loss")
plt.plot(np.arange( 0100), H.history[ "acc"],  label= "train_acc")
plt.plot(np.arange( 0100), H.history[ "val_acc"],  label= "val_acc")
plt.title( "Training Loss and Accuracy")
plt.xlabel( "Epoch #")
plt.ylabel( "Loss/Accuracy")
plt.legend()
plt.show()

这里我使用的数据库为网络上出名的dogs vs cats的数据库,我分别取了2000个狗和猫的图片进行分类。

注意这里非常重要的就是之前讲的分类图片文件夹的建立,

我这里的文件夹名称为 C:\animals   

在这个文件夹下面有C:\animals\cats和C:\animals\dogs,里面分别存图片。

在command windows里面输入以下的程序,就可以开始训练啦:

$ python shallownet_animals.py --dataset C:/animals

三. 总结

谢谢大家的学习,这个是我学习机器学习几个月来第一次写文来分享,如果有任何问题可以留言。

现在就可以开始训练自己的网络啦,后续我也会继续介绍其他的更加复杂的网络。

参考文献:

Howse J, Minichino J. Learning OpenCV 3 Computer Vision with Python[J]. 2015.


                                      

你可能感兴趣的:(卷积神经,cnn,图片转换为矩阵,keras,python)