一文理解tensorflow卷積神經網絡

卷積與池化操作

model = keras.models.Sequential() #先生成一個模型框架
model.add(keras.layers.Conv2D(filters = 32, #卷積核個數,卷積核越多掃描出的特徵越多
                              kernel_size = 3,#卷積核的大小
                              padding = 'same',#掃描後圖片大小的模式
                              activation = 'selu',#激活函數
                              input_shape = (28,28,1)#輸入模型的大小
                              ))
model.add(keras.layers.Conv2D(filters = 32,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'selu',
                              ))
model.add(keras.layers.MaxPool2D(pool_size = 2))#池化掃描的大小
#此處還有一個AveragePooling2D平均池化

一般的模型

google v3

在這裏插入圖片描述

深度可分離神經網絡

在這裏插入圖片描述

實例代碼

卷積神經網絡

model = keras.models.Sequential() #先生成一個模型框架
model.add(keras.layers.Conv2D(filters = 32,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              input_shape = (28,28,1)
                              ))
model.add(keras.layers.BatchNormalization())                              
model.add(keras.layers.Conv2D(filters = 32,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())  
model.add(keras.layers.MaxPool2D(pool_size = 2))
model.add(keras.layers.Dropout(0.3))
model.add(keras.layers.Conv2D(filters = 64,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())                                
model.add(keras.layers.Conv2D(filters = 64,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())                                
model.add(keras.layers.MaxPool2D(pool_size = 2))
model.add(keras.layers.Dropout(0.3))
model.add(keras.layers.Conv2D(filters = 128,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())                                
model.add(keras.layers.Conv2D(filters = 128,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())                                
model.add(keras.layers.MaxPool2D(pool_size = 2))
model.add(keras.layers.Dropout(0.4))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(256,activation = 'relu'))
model.add(keras.layers.Dropout(0.5))
model.add(keras.layers.Dense(256,activation = 'tanh'))
model.add(keras.layers.Dropout(0.5))
model.add(keras.layers.Dense(10,activation = 'softmax'))
model.summary()

深度可分離卷積神經網絡

model = keras.models.Sequential() #先生成一個模型框架
model.add(keras.layers.Conv2D(filters = 32,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'selu',
                              input_shape = (28,28,1)
                              ))
model.add(keras.layers.SeparableConv2D(filters = 32,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'selu',
                              ))
model.add(keras.layers.MaxPool2D(pool_size = 2))
model.add(keras.layers.SeparableConv2D(filters = 64,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'selu',
                              ))
model.add(keras.layers.SeparableConv2D(filters = 64,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'selu',
                              ))
model.add(keras.layers.MaxPool2D(pool_size = 2))
model.add(keras.layers.SeparableConv2D(filters = 128,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'selu',
                              ))
model.add(keras.layers.SeparableConv2D(filters = 128,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'selu',
                              ))
model.add(keras.layers.MaxPool2D(pool_size = 2))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(128,activation = 'selu'))
model.add(keras.layers.Dense(10,activation = 'softmax'))

實戰 10 Monkey數據集

包含相應庫文件

import numpy as np 
import pandas as pd 
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import os

設置文件路徑並讀取標籤

train_dir = "../input/10-monkey-species/training/training"#引入訓練集路徑
valid_dir = "../input/10-monkey-species/validation/validation"#引入驗證集路徑
label_file = "../input/10-monkey-species/monkey_labels.txt"#引入標籤文件
print(os.path.exists(train_dir))#查看train_dir路徑是否存在
print(os.path.exists(valid_dir))#查看calid_dir路徑是否存在
print(os.path.exists(label_file))#查看label_file路徑是否存在
print(os.listdir(train_dir))
print(os.listdir(valid_dir))
labels = pd.read_csv(label_file, header = (0))#調用pandas讀取csv文件,header設置表頭爲第一行
print(labels)   

設置宏定義

height = 128 #設置宏變量,所有圖片的高度都變成此高度
width = 128  #設置宏變量,所有圖片的寬度都變成此寬度
channels = 3 #設置宏變量,所有圖片的深度都變成此深度
batch_size = 128 #設置宏變量,設置每一批訓練的數據多少
num_classes = 10 #設置宏變量,設置我們要劃分的類別數目
epochs = 300 #設置宏變量,定義訓練多少遍

讀取圖片並做數據增強

train_datagen = keras.preprocessing.image.ImageDataGenerator(
    rescale = 1./255.,#把所有的像素點都乘上這個數,一般用於歸一化
    rotation_range = 40,#把所有圖片隨機旋轉一個角度,旋轉範圍是正負這個數
    width_shift_range = 0.2,#橫向位移增強所有圖片在隨機這個數×100%的範圍進行位移
    height_shift_range = 0.2,#縱向位移增強所有圖片在隨機這個數×100%的範圍進行位移
    shear_range = 0.2,#剪切強度
    zoom_range = 0.2,#縮放強度
    horizontal_flip = True,#是否隨機的進行水平翻轉
    fill_mode = 'nearest',#如果需要填充像素點那麼以什麼策略填充(現在是離他最近的真實像素點)
#讀取圖片並數據增強
train_generator = train_datagen.flow_from_directory(
    train_dir,#文件路徑
    target_size = (height,width),#所有圖片都縮放成這個長寬
    batch_size = batch_size,#定義沒一批數據都有多少個
    seed = 7,#用來做隨機的(可以隨便輸)
    shuffle = True,#是否打亂順序
    class_mode = "categorical"#編碼方式 one—hot之前還是之後(這裏選用的是之後)  
)
#設置驗證集的圖片預處理方式
vaild_datagen = keras.preprocessing.image.ImageDataGenerator(rescale = 1./255.)
#對驗證集進行同樣的整理(唯一就是不用打亂順序)
valid_generator = vaild_datagen.flow_from_directory(
    valid_dir,#文件路徑
    target_size = (height,width),#所有圖片都縮放成這個長寬
    batch_size = batch_size,#定義沒一批數據都有多少個
    seed = 7,#用來做隨機的(可以隨便輸)
    class_mode = "categorical"#編碼方式 one—hot之前還是之後(這裏選用的是之後)  
)
#打印數據數目
train_num = train_generator.samples
valid_num = valid_generator.samples
print(train_num, valid_num)              

取數據

for i in range(2):
    x,y = train_generator.next()
    print(x.shape,y.shape)
    print(y)

構建神經網絡

model = keras.models.Sequential() #先生成一個模型框架
model.add(keras.layers.Conv2D(filters = 32,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              input_shape = (28,28,1)
                              ))
model.add(keras.layers.BatchNormalization())                              
model.add(keras.layers.Conv2D(filters = 32,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())  
model.add(keras.layers.MaxPool2D(pool_size = 2))
model.add(keras.layers.Dropout(0.3))
model.add(keras.layers.Conv2D(filters = 64,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())                                
model.add(keras.layers.Conv2D(filters = 64,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())                                
model.add(keras.layers.MaxPool2D(pool_size = 2))
model.add(keras.layers.Dropout(0.3))
model.add(keras.layers.Conv2D(filters = 128,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())                                
model.add(keras.layers.Conv2D(filters = 128,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())                                
model.add(keras.layers.MaxPool2D(pool_size = 2))
model.add(keras.layers.Dropout(0.4))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(256,activation = 'relu'))
model.add(keras.layers.Dropout(0.5))
model.add(keras.layers.Dense(256,activation = 'tanh'))
model.add(keras.layers.Dropout(0.5))
model.add(keras.layers.Dense(10,activation = 'softmax'))
model.summary()

定義求解方法

model.compile(optimizer='adam',#求解模型的方法
             loss='categorical_crossentropy',#損失函數必須是向量如果已經是向量可省略sparse_
             metrics=['accuracy'])#將其他參數加入到圖中,並將圖固化

訓練模型

history = model.fit_generator(train_generator,#前面用到的生成器
             steps_per_epoch = train_num // batch_size,#生成器會無限循環數據,所以要設置他的步數(注意不是步長)
             epochs = epochs,#訓練多少輪
             validation_data = valid_generator,#驗證數據的生成器
             validation_steps =valid_num // batch_size #生成器會無限循環數據,所以要設置他的步數(注意不是步長)

可視化模型訓練

#可視化訓練過程                             
def plot_learning_curves(history,label,epcohs,min_value,max_value):
    data={}
    data[label] = history.history[label]
    data['val_'+label] = history.history['val_'+label]
    pd.DataFrame(data).plot(figsize = (8,5))
    plt.grid(True)
    plt.axis([0,epcohs,min_value,max_value])
    plt.show()
plot_learning_curves(history,'accuracy',10,0,1)#分別模型訓練時的返回值,一共訓練了幾輪,y軸顯示下限,y軸顯示上限
plot_learning_curves(history,'loss',10,1.5,2.5)#分別模型訓練時的返回值,一共訓練了幾輪,y軸顯示下限,y軸顯示上限

全部代碼

#包含相應庫文件
import numpy as np 
import pandas as pd 
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import os
train_dir = "../input/10-monkey-species/training/training"#引入訓練集路徑
valid_dir = "../input/10-monkey-species/validation/validation"#引入驗證集路徑
label_file = "../input/10-monkey-species/monkey_labels.txt"#引入標籤文件
print(os.path.exists(train_dir))#查看train_dir路徑是否存在
print(os.path.exists(valid_dir))#查看calid_dir路徑是否存在
print(os.path.exists(label_file))#查看label_file路徑是否存在
print(os.listdir(train_dir))
print(os.listdir(valid_dir))
labels = pd.read_csv(label_file, header = (0))#調用pandas讀取csv文件,header設置表頭爲第一行
print(labels)   
height = 128 #設置宏變量,所有圖片的高度都變成此高度
width = 128  #設置宏變量,所有圖片的寬度都變成此寬度
channels = 3 #設置宏變量,所有圖片的深度都變成此深度
batch_size = 128 #設置宏變量,設置每一批訓練的數據多少
num_classes = 10 #設置宏變量,設置我們要劃分的類別數目
epochs = 300 #設置宏變量,定義訓練多少遍

#定義keras裏的ImageDataGenerator圖片數據增強的參數
train_datagen = keras.preprocessing.image.ImageDataGenerator(
    rescale = 1./255.,#把所有的像素點都乘上這個數,一般用於歸一化
    rotation_range = 40,#把所有圖片隨機旋轉一個角度,旋轉範圍是正負這個數
    width_shift_range = 0.2,#橫向位移增強所有圖片在隨機這個數×100%的範圍進行位移
    height_shift_range = 0.2,#縱向位移增強所有圖片在隨機這個數×100%的範圍進行位移
    shear_range = 0.2,#剪切強度
    zoom_range = 0.2,#縮放強度
    horizontal_flip = True,#是否隨機的進行水平翻轉
    fill_mode = 'nearest',#如果需要填充像素點那麼以什麼策略填充(現在是離他最近的真實像素點)
)
#讀取圖片並數據增強
train_generator = train_datagen.flow_from_directory(
    train_dir,#文件路徑
    target_size = (height,width),#所有圖片都縮放成這個長寬
    batch_size = batch_size,#定義沒一批數據都有多少個
    seed = 7,#用來做隨機的(可以隨便輸)
    shuffle = True,#是否打亂順序
    class_mode = "categorical"#編碼方式 one—hot之前還是之後(這裏選用的是之後)  
)
#設置驗證集的圖片預處理方式
vaild_datagen = keras.preprocessing.image.ImageDataGenerator(rescale = 1./255.)
#對驗證集進行同樣的整理(唯一就是不用打亂順序)
valid_generator = vaild_datagen.flow_from_directory(
    valid_dir,#文件路徑
    target_size = (height,width),#所有圖片都縮放成這個長寬
    batch_size = batch_size,#定義沒一批數據都有多少個
    seed = 7,#用來做隨機的(可以隨便輸)
    class_mode = "categorical"#編碼方式 one—hot之前還是之後(這裏選用的是之後)  
)
train_num = train_generator.samples
valid_num = valid_generator.samples
print(train_num, valid_num)              
#取數據
for i in range(2):
    x,y = train_generator.next()
    print(x.shape,y.shape)
    print(y)
#定義模型
model = keras.models.Sequential() #先生成一個模型框架
model.add(keras.layers.Conv2D(filters = 32,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              input_shape = (28,28,1)
                              ))
model.add(keras.layers.BatchNormalization())                              
model.add(keras.layers.Conv2D(filters = 32,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())  
model.add(keras.layers.MaxPool2D(pool_size = 2))
model.add(keras.layers.Dropout(0.3))
model.add(keras.layers.Conv2D(filters = 64,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())                                
model.add(keras.layers.Conv2D(filters = 64,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())                                
model.add(keras.layers.MaxPool2D(pool_size = 2))
model.add(keras.layers.Dropout(0.3))
model.add(keras.layers.Conv2D(filters = 128,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())                                
model.add(keras.layers.Conv2D(filters = 128,
                              kernel_size = 3,
                              padding = 'same',
                              activation = 'relu',
                              ))
model.add(keras.layers.BatchNormalization())                                
model.add(keras.layers.MaxPool2D(pool_size = 2))
model.add(keras.layers.Dropout(0.4))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(256,activation = 'relu'))
model.add(keras.layers.Dropout(0.5))
model.add(keras.layers.Dense(256,activation = 'tanh'))
model.add(keras.layers.Dropout(0.5))
model.add(keras.layers.Dense(10,activation = 'softmax'))
model.summary() 
model.compile(optimizer='adam',#求解模型的方法
             loss='categorical_crossentropy',#損失函數必須是向量如果已經是向量可省略sparse_
             metrics=['accuracy'])#將其他參數加入到圖中,並將圖固化
history = model.fit_generator(train_generator,#前面用到的生成器
             steps_per_epoch = train_num // batch_size,#生成器會無限循環數據,所以要設置他的步數(注意不是步長)
             epochs = epochs,#訓練多少輪
             validation_data = valid_generator,#驗證數據的生成器
             validation_steps =valid_num // batch_size #生成器會無限循環數據,所以要設置他的步數(注意不是步長)
#可視化訓練過程                             
def plot_learning_curves(history,label,epcohs,min_value,max_value):
    data={}
    data[label] = history.history[label]
    data['val_'+label] = history.history['val_'+label]
    pd.DataFrame(data).plot(figsize = (8,5))
    plt.grid(True)
    plt.axis([0,epcohs,min_value,max_value])
    plt.show()
plot_learning_curves(history,'acc',10,0,1)#分別模型訓練時的返回值,一共訓練了幾輪,y軸顯示下限,y軸顯示上限
plot_learning_curves(history,'loss',10,1.5,2.5)#分別模型訓練時的返回值,一共訓練了幾輪,y軸顯示下限,y軸顯示上限
                   )

遷移學習

模型獲取

from keras.applications.xception import Xception
from keras.applications.vgg16 import VGG16
from keras.applications.vgg19 import VGG19
from keras.applications.resnet import ResNet50
from keras.applications.resnet import ResNet101
from keras.applications.resnet import ResNet152
from keras.applications.resnet_v2 import ResNet50V2
from keras.applications.resnet_v2 import ResNet101V2
from keras.applications.resnet_v2 import ResNet152V2
from keras.applications.resnext import ResNeXt50
from keras.applications.resnext import ResNeXt101
from keras.applications.inception_v3 import InceptionV3
from keras.applications.inception_resnet_v2 import InceptionResNetV2
from keras.applications.mobilenet import MobileNet
from keras.applications.mobilenet_v2 import MobileNetV2
from keras.applications.densenet import DenseNet121
from keras.applications.densenet import DenseNet169
from keras.applications.densenet import DenseNet201
from keras.applications.nasnet import NASNetLarge
from keras.applications.nasnet import NASNetMobile

model = VGG16(weights='imagenet', include_top=True)

調整輸入大小

每個模型都有自己的輸入大小所以要去官網查一下
在這裏使用的ResNet是 224×224的

設置同樣的數據輸入處理

#定義keras裏的ImageDataGenerator圖片數據增強的參數
train_datagen = keras.preprocessing.image.ImageDataGenerator(
    preprocessing_function = keras.applications.resnet50.preprocess_input,#在這裏按照不同的方法對模型進行輸入處理
    rotation_range = 40,#把所有圖片隨機旋轉一個角度,旋轉範圍是正負這個數
    width_shift_range = 0.2,#橫向位移增強所有圖片在隨機這個數×100%的範圍進行位移
    height_shift_range = 0.2,#縱向位移增強所有圖片在隨機這個數×100%的範圍進行位移
    shear_range = 0.2,#剪切強度
    zoom_range = 0.2,#縮放強度
    horizontal_flip = True,#是否隨機的進行水平翻轉
    fill_mode = 'nearest',#如果需要填充像素點那麼以什麼策略填充(現在是離他最近的真實像素點)點
)

獲取模型和自己的層次進行拼接

model = keras.models.Sequential() #先生成一個模型框架
model.add(keras.applications.ResNet50(
    include_top = False, #是否去掉最後的那些全連接層
    pooling = 'avg',#因爲去掉後是卷積層所以要把數據展平
    weights = 'imagenet',#設置權重是什麼數據集的
))
model.add(keras.layers.Dense(num_classes, activation = 'softmax'))#添加我們加入的全連接層
model.layers[0].trainable = False #凍結住層一,讓他的參數不再變化
model.summary()


#或者微調模型
resnet50 = keras.applications.ResNet50(
    include_top = False,#是否去掉最後的那些全連接層
    pooling = 'avg',#因爲去掉後是卷積層所以要把數據展平
    weights = 'imagenet',#設置權重是什麼數據集的
for layer in resnet50.layers[0:-5]:#在這裏遍歷層次(從第幾層,到第幾層)
    layer.trainable = False#關閉該層的可訓練開關
model = keras.models.Sequential([
    resnet50,
    keras.layers.Dense(num_classes, activation = 'softmax'),
])
)

定義模型求解方式和訓練模型

model.compile(optimizer='sgd',#sgd求解模型時間長,但可以達到極小值
             loss='categorical_crossentropy',#損失函數必須是向量如果已經是向量可省略sparse_
             metrics=['accuracy'])#將其他參數加入到圖中,並將圖固化
epochs = 10#定義模型中的訓練輪數
history = model.fit_generator(train_generator,
                             steps_per_epoch = train_num // batch_size,
                             epochs = epochs,
                             validation_data = valid_generator,
                             validation_steps =valid_num // batch_size 
                   )

可視化模型

def plot_learning_curves(history,label,epochs,min_value,max_value):
    data={}
    data[label] = history.history[label]
    data['val_'+label] = history.history['val_'+label]
    pd.DataFrame(data).plot(figsize = (8,5))
    plt.grid(True)
    plt.axis([0,epochs,min_value,max_value])
    plt.show()
plot_learning_curves(history,'accuracy',epochs,0,1)
plot_learning_curves(history,'loss',epochs,0,2.5)

ResNet50遷移學習實戰cifar-10 95%

包含庫文件

import numpy as np
import pandas as pd 
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
from sklearn import preprocessing
import cv2
import os

獲取數據

(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data()#從keras指定的地方下載cifar-10數據集並劃分訓練集測試集

數據處理

創建保存data的文件夾

train_dir = '/kaggle/working/train'#設置訓練數據存放在哪裏
test_dir = '/kaggle/working/test'#設置測試數據存放在哪裏
if  not (os.path.exists(train_dir)):#如果沒有訓練數據存放的文件夾
    os.makedirs(train_dir)         #就創建這個文件夾
if  not (os.path.exists(test_dir)):#如果沒有測試數據存放的文件夾
    os.makedirs(test_dir)          #就創建這個文件夾

寫入數據 並按照(文件路徑/標籤)的形式返回數據存放信息

def save_data(x_train, y_train, path):
    data_amount = len(x_train)
    assert(data_amount == len(y_train)), '數據與標籤不匹配'
    assert(y_train.shape[1] == 1), '標籤必須是一列數據'
    assert(os.path.exists(path)), '填寫的目錄不存在'
    _list = []
    for i in range(data_amount):
        cv2.imwrite( "{}/data_{}.png".format(path,i), x_train[i])
        _list.append(["{}/data_{}.png".format(path,i),'{}'.format(y_train[i][0])])
    data_pd = pd.DataFrame(_list)
    data_pd.columns = ['filepath','class']
    del _list
    return data_pd
train_pd = save_data(x_train, y_train, train_dir)#填寫數據集,標籤,和存放目錄
test_pd = save_data(x_test, y_test, test_dir)#填寫數據集,標籤,和存放目錄

設置宏變量

height = 224 #設置宏變量,所有圖片的高度都變成此高度
width = 224  #設置宏變量,所有圖片的寬度都變成此寬度
channels = 3 #設置宏變量,所有圖片的深度都變成此深度
batch_size = 20 #設置宏變量,設置每一批訓練的數據多少
num_classes = 10 #設置宏變量,設置我們要劃分的類別數目
epochs = 10 #設置宏變量,定義訓練多少遍

數據增強

train_datagen = keras.preprocessing.image.ImageDataGenerator(
    preprocessing_function = keras.applications.resnet50.preprocess_input,#resnet50獨有的數據處理方法
    rotation_range = 40,#設置隨機旋轉多少角度
    width_shift_range = 0.2,#設置隨機橫向位移百分比
    height_shift_range = 0.2,#設置隨機縱向位移百分比
    shear_range = 0.2,#設置剪切強度
    zoom_range = 0.2,#設置縮放強度
    horizontal_flip = True,#是否隨機的進行水平翻轉
    fill_mode = 'nearest',#編碼方式 one—hot之前還是之後(這裏選用的是之前) 
)
test_datagen = keras.preprocessing.image.ImageDataGenerator(
    preprocessing_function = keras.applications.resnet50.preprocess_input,#resnet50獨有的數據處理方法
)
train_generator = train_datagen.flow_from_dataframe(
    train_pd, #包含需要處理的數據文件目錄和標籤的panadas
    directory = '/kaggle',#設置根目錄
    x_col = 'filepath',#數據列名
    y_col = 'class',#標籤列名
    target_size = (height,width),#圖片將縮放成這個大小
    batch_size = batch_size,#沒一批處理多少數據
    seed = 7,#隨機數種子
    shuffle = True,#是否打亂順序
    class_mode = 'categorical',#編碼方式 one—hot之前還是之後(這裏選用的是之後)  
)
#測試集不需要打亂順序
test_generator = test_datagen.flow_from_dataframe(
    test_pd,#包含需要處理的數據文件目錄和標籤的panadas
    directory = '/kaggle',#設置根目錄
    x_col = 'filepath',#數據列名
    y_col = 'class',#標籤列名
    target_size = (height,width),#圖片將縮放成這個大小
    batch_size = batch_size,#沒一批處理多少數據
    seed = 7,#隨機數種子
    class_mode = 'categorical',#編碼方式 one—hot之前還是之後(這裏選用的是之後) 
)

定義模型

keras.backend.set_learning_phase(0)
Inp = keras.layers.Input((224, 224, 3))
base_model = keras.applications.ResNet50(weights='imagenet', include_top=False,
                              input_shape=(height, width, 3), )
keras.backend.set_learning_phase(1)
x = base_model(Inp)
x = keras.layers.BatchNormalization()(x, training=False)
x = keras.layers.GlobalAveragePooling2D(name='average_pool')(x)
x = keras.layers.Flatten(name='flatten')(x)
x = keras.layers.Dense(2048, activation='relu')(x)
x = keras.layers.Dense(1024, activation='tanh')(x)
predictions = keras.layers.Dense(num_classes, activation='softmax')(x)
model = keras.Model(inputs=Inp, outputs=predictions)

定義模型優化方法

model.compile(optimizer='sgd',#sgd求解模型時間長,但可以達到極小值
             loss='categorical_crossentropy',#損失函數必須是向量如果已經是向量可省略sparse_
             metrics=['accuracy'])#將其他參數加入到圖中,並將圖固化

訓練數據

history = model.fit_generator(train_generator,#前面用到的生成器
                             steps_per_epoch = len(train_pd) // batch_size,#生成器會無限循環數據,所以要設置他的步數(注意不是步長)
                             epochs = epochs,#訓練多少輪
                             validation_data = test_generator,#驗證數據的生成器
                             validation_steps = len(test_pd) // batch_size #生成器會無限循環數據,所以要設置他的步數(注意不是步長)

可視化訓練結果

def plot_learning_curves(history,label,epochs,min_value,max_value):
    data={}
    data[label] = history.history[label]
    data['val_'+label] = history.history['val_'+label]
    pd.DataFrame(data).plot(figsize = (8,5))
    plt.grid(True)
    plt.axis([0,epochs,min_value,max_value])
    plt.show()
plot_learning_curves(history,'accuracy',epochs,0,1)
plot_learning_curves(history,'loss',epochs,0,2.5)  

全部代碼

#包含所需要的庫文件
import numpy as np
import pandas as pd 
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
from sklearn import preprocessing
import cv2
import os
#獲取數據
(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data()
#配置文件路徑,創建train和test兩個文件夾
train_dir = '/kaggle/working/train'
test_dir = '/kaggle/working/test'
if  not (os.path.exists(train_dir)):
    os.makedirs(train_dir)
if  not (os.path.exists(test_dir)):
    os.makedirs(test_dir)
#將數據寫入文件夾,並按照(文件目錄,標籤)的模式寫好pandas
def save_data(x_train, y_train, path):
    data_amount = len(x_train)
    assert(data_amount == len(y_train)), '數據與標籤不匹配'
    assert(y_train.shape[1] == 1), '標籤必須是一列數據'
    assert(os.path.exists(path)), '填寫的目錄不存在'
    _list = []
    for i in range(data_amount):
        cv2.imwrite( "{}/data_{}.png".format(path,i), x_train[i])
        _list.append(["{}/data_{}.png".format(path,i),'{}'.format(y_train[i][0])])
    data_pd = pd.DataFrame(_list)
    data_pd.columns = ['filepath','class']
    del _list
    return data_pd
train_pd = save_data(x_train, y_train, train_dir)
test_pd = save_data(x_test, y_test, test_dir)
#設置宏變量
height = 224 #設置宏變量,所有圖片的高度都變成此高度
width = 224  #設置宏變量,所有圖片的寬度都變成此寬度
channels = 3 #設置宏變量,所有圖片的深度都變成此深度
batch_size = 20 #設置宏變量,設置每一批訓練的數據多少
num_classes = 10 #設置宏變量,設置我們要劃分的類別數目
epochs = 10 #設置宏變量,定義訓練多少遍
#定義keras裏的ImageDataGenerator圖片數據增強的參數
train_datagen = keras.preprocessing.image.ImageDataGenerator(
    preprocessing_function = keras.applications.resnet50.preprocess_input,
    rotation_range = 40,
    width_shift_range = 0.2,
    height_shift_range = 0.2,
    shear_range = 0.2,
    zoom_range = 0.2,
    horizontal_flip = True,
    fill_mode = 'nearest',
)
test_datagen = keras.preprocessing.image.ImageDataGenerator(
    preprocessing_function = keras.applications.resnet50.preprocess_input,
)
train_generator = train_datagen.flow_from_dataframe(
    train_pd,
    directory = '/kaggle',
    x_col = 'filepath',
    y_col = 'class',
    target_size = (height,width),
    batch_size = batch_size,
    seed = 7,
    shuffle = True,
    class_mode = 'categorical',
)
test_generator = test_datagen.flow_from_dataframe(
    test_pd,
    directory = '/kaggle',
    x_col = 'filepath',
    y_col = 'class',
    target_size = (height,width),
    batch_size = batch_size,
    seed = 7,
    class_mode = 'categorical',
)
#設置模型
keras.backend.set_learning_phase(0)
Inp = keras.layers.Input((224, 224, 3))
base_model = keras.applications.ResNet50(weights='imagenet', include_top=False,
                              input_shape=(height, width, 3), )
keras.backend.set_learning_phase(1)
x = base_model(Inp)
x = keras.layers.BatchNormalization()(x, training=False)
x = keras.layers.GlobalAveragePooling2D(name='average_pool')(x)
x = keras.layers.Flatten(name='flatten')(x)
x = keras.layers.Dense(2048, activation='relu')(x)
x = keras.layers.Dense(1024, activation='tanh')(x)
predictions = keras.layers.Dense(num_classes, activation='softmax')(x)
model = keras.Model(inputs=Inp, outputs=predictions)
#設置求解模型的方法
model.compile(optimizer='sgd',
             loss='categorical_crossentropy',
             metrics=['accuracy'])
#訓練數據             
history = model.fit_generator(train_generator,
                             steps_per_epoch = len(train_pd) // batch_size,
                             epochs = epochs,
                             validation_data = test_generator,
                             validation_steps = len(test_pd) // batch_size 
                   )
#可視化數據                   
def plot_learning_curves(history,label,epochs,min_value,max_value):
    data={}
    data[label] = history.history[label]
    data['val_'+label] = history.history['val_'+label]
    pd.DataFrame(data).plot(figsize = (8,5))
    plt.grid(True)
    plt.axis([0,epochs,min_value,max_value])
    plt.show()
plot_learning_curves(history,'accuracy',epochs,0,1)
plot_learning_curves(history,'loss',epochs,0,2.5)                   

cnn總結

輸入感受野維度:圖像的默認值爲 2D,但可以是 1D,例如句子中的單詞或添加時間維度的視頻的 3D。
感受野的大小:patch應儘可能小,但應該大到足以“看到”輸入數據中的特徵,通常在小圖像上使用 3×3,在較大圖像尺寸上使用 5×57×7 或更多。
步幅寬度:使用默認步幅 1.這很容易理解,並且您不需要填充來處理從圖像邊緣掉落的感受野。對於較大的圖像,這可以增加到 2 或更大。
濾波器數量:濾波器是特徵檢測器,通常在輸入層使用較少的濾波器,並且在較深層使用的濾波器越來越多。
填充:設置爲零並在讀取非輸入數據時調用零填充。當您不能或不想標準化輸入圖像大小或想要使用不能整齊劃分輸入圖像大小的感知字段和步幅大小時,這將非常有用。
池化:池化是一種破壞性或泛化過程,以減少過擬合,感受野幾乎總是設置爲 2×2,步幅爲 2,以丟棄前一層輸出的 75%激活。
數據準備:考慮標準化輸入數據,包括圖像尺寸和像素值。
模式體系結構:通常在網絡體系結構中對層進行模式化。這可能是一個,兩個或一些卷積層,後面是池化層。然後可以重複該結構一次或多次。最後,完全連接層通常僅在輸出端使用,並且可以堆疊一個,兩個或更多個深度。
dropout:CNN 容易造成一種過擬合,即使是池化層也是如此,應該在完全連接的層之間,或池化層之後使用Dropout。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章