加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • MNIST手寫數(shù)字識(shí)別
    • 狗的品種識(shí)別
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

一文了解深度學(xué)習(xí)實(shí)戰(zhàn)——分類篇

05/04 08:05
1539
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

本文將從兩個(gè)案例 MNIST手寫數(shù)字識(shí)別、狗的品種識(shí)別 入手,讓童鞋們從實(shí)戰(zhàn)角度快速入門深度學(xué)習(xí)的分類部分!

MNIST手寫數(shù)字識(shí)別

TensorFlow搭建MLP

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

# 下載數(shù)據(jù)集
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

print("訓(xùn)練集圖像大小:{}".format(mnist.train.images.shape))
print("訓(xùn)練集標(biāo)簽大?。簕}".format(mnist.train.labels.shape))
print("驗(yàn)證集圖像大小:{}".format(mnist.validation.images.shape))
print("驗(yàn)證集標(biāo)簽大?。簕}".format(mnist.validation.labels.shape))
print("測(cè)試集圖像大?。簕}".format(mnist.test.images.shape))
print("測(cè)試集標(biāo)簽大小:{}".format(mnist.test.labels.shape))

# 為了便于讀取,我們把數(shù)據(jù)集先各自使用一個(gè)變量指向它們
x_train, y_train = mnist.train.images, mnist.train.labels
x_valid, y_valid = mnist.validation.images, mnist.validation.labels
x_test, y_test = mnist.test.images, mnist.test.labels

# 繪制和顯示前5個(gè)訓(xùn)練集的圖像 
fig = plt.figure(figsize=(10, 10))
for i in range(5):
    ax = fig.add_subplot(1, 5, i+1, xticks=[], yticks=[])
    ax.imshow(np.reshape(x_train[i:i+1], (28, 28)), cmap='gray')
# 繪制和顯示前(2*12)之后的五個(gè)訓(xùn)練集的圖像 
fig = plt.figure(figsize=(10, 10))
for i in range(5):
    ax = fig.add_subplot(1, 5, i+1, xticks=[], yticks=[])
    ax.imshow(np.reshape(x_train[i+2*12:i+1+2*12], (28, 28)), cmap='gray')

# 定義可視化圖像的函數(shù),傳入一個(gè)圖像向量和figure對(duì)象
def visualize_input(img, ax):
    # 繪制并輸出圖像
    ax.imshow(img, cmap='gray')
    
    # 對(duì)于該圖像的寬和高,我們輸出它們的具體的數(shù)值,
    # 以便于我們更清晰的知道計(jì)算機(jī)是如何看待一張圖像的
    width, height = img.shape
    
    # 將圖像中的具體數(shù)值轉(zhuǎn)換成0-1之間的值
    thresh = img.max()/2.5 
    # 遍歷行
    for x in range(width):
        # 遍歷列
        for y in range(height):
            # 將圖像的數(shù)值在它對(duì)應(yīng)的位置上標(biāo)出,且水平垂直居中
            ax.annotate(str(round(img[x][y],2)), xy=(y,x),
                        horizontalalignment='center',
                        verticalalignment='center',
                        color='white' if img[x][y]<thresh else 'black')

fig = plt.figure(figsize=(10, 10)) 
ax = fig.add_subplot(111)
# 假設(shè)我們就取出下標(biāo)為5的樣本來(lái)作為例子
visualize_input(np.reshape(x_train[5:6], (28, 28)), ax)


import math
#模型搭建和訓(xùn)練
# 參數(shù)準(zhǔn)備
img_size = 28 * 28
num_classes = 10
learning_rate = 0.1
epochs = 100
batch_size = 128

# 創(chuàng)建模型
# x表示輸入,創(chuàng)建輸入占位符,該占位符會(huì)在訓(xùn)練時(shí),會(huì)對(duì)每次迭代的數(shù)據(jù)進(jìn)行填充上
x = tf.placeholder(tf.float32, [None, img_size])

# W表示weight,創(chuàng)建權(quán)重,初始化時(shí)都是為0,它的大小是(圖像的向量大小,圖像的總類別)
W = tf.Variable(tf.zeros([img_size, num_classes]))

# b表示bias,創(chuàng)建偏移項(xiàng)
b = tf.Variable(tf.zeros([num_classes]))

# y表示計(jì)算輸出結(jié)果,softmax表示激活函數(shù)是多類別分類的輸出
# 感知器的計(jì)算公式就是:(x * W) + b
y = tf.nn.softmax(tf.matmul(x, W) + b)

# 定義輸出預(yù)測(cè)占位符y_
y_ = tf.placeholder(tf.float32, [None, 10])

valid_feed_dict = { x: x_valid, y_: y_valid  }
test_feed_dict = { x: x_test, y_: y_test }

# 通過(guò)激活函數(shù)softmax的交叉熵來(lái)定義損失函數(shù)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))
# 定義梯度下降優(yōu)化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

# 比較正確的預(yù)測(cè)結(jié)果
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
# 計(jì)算預(yù)測(cè)準(zhǔn)確率
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    
iteration = 0
# 定義訓(xùn)練時(shí)的檢查點(diǎn)
saver = tf.train.Saver()

# 創(chuàng)建一個(gè)TensorFlow的會(huì)話
with tf.Session() as sess:
  
    # 初始化全局變量
    sess.run(tf.global_variables_initializer())
        
    # 根據(jù)每批次訓(xùn)練128個(gè)樣本,計(jì)算出一共需要迭代多少次
    batch_count = int(math.ceil(mnist.train.labels.shape[0] / 128.0))
    
    # 開(kāi)始迭代訓(xùn)練樣本
    for e in range(epochs):
        
        # 每個(gè)樣本都需要在TensorFlow的會(huì)話里進(jìn)行運(yùn)算,訓(xùn)練
        for batch_i in range(batch_count):
          
            # 樣本的索引,間隔是128個(gè)
            batch_start = batch_i * batch_size
            # 取出圖像樣本
            batch_x = mnist.train.images[batch_start:batch_start+batch_size]
            # 取出圖像對(duì)應(yīng)的標(biāo)簽
            batch_y = mnist.train.labels[batch_start:batch_start+batch_size]
            # 訓(xùn)練模型
            loss, _ = sess.run([cost, optimizer], feed_dict={x: batch_x, y_: batch_y})
            
            # 每20個(gè)批次時(shí)輸出一次訓(xùn)練損失等日志信息
            if batch_i % 20 == 0:
                print("Epoch: {}/{}".format(e+1, epochs), 
                      "Iteration: {}".format(iteration), 
                      "Training loss: {:.5f}".format(loss))
            iteration += 1

            # 每128個(gè)樣本時(shí),驗(yàn)證一下訓(xùn)練的效果如何,并輸出日志信息
            if iteration % batch_size == 0:
                valid_acc = sess.run(accuracy, feed_dict=valid_feed_dict)
                print("Epoch: {}/{}".format(e, epochs),
                      "Iteration: {}".format(iteration),
                      "Validation Accuracy: {:.5f}".format(valid_acc))
    
    # 保存訓(xùn)練模型的檢查點(diǎn)
    saver.save(sess, "checkpoints/mnist_mlp_tf.ckpt")

# 預(yù)測(cè)測(cè)試數(shù)據(jù)集精確度
saver = tf.train.Saver()
with tf.Session() as sess:
    # 從訓(xùn)練模型的檢查點(diǎn)恢復(fù)
    saver.restore(sess, tf.train.latest_checkpoint('checkpoints'))
    
    # 預(yù)測(cè)測(cè)試集精確度
    test_acc = sess.run(accuracy, feed_dict=test_feed_dict)
    print("test accuracy: {:.5f}".format(test_acc))

TensorFlow搭建CNN

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 下載并加載數(shù)據(jù)集
mnist = input_data.read_data_sets('MNIST_data/', one_hot=True)

# 為了便于讀取,我們把數(shù)據(jù)集先各自使用一個(gè)變量指向它們
x_train, y_train = mnist.train.images, mnist.train.labels
x_valid, y_valid = mnist.validation.images, mnist.validation.labels
x_test, y_test = mnist.test.images, mnist.test.labels

print("訓(xùn)練集圖像大?。簕}".format(x_train.shape))
print("訓(xùn)練集標(biāo)簽大?。簕}".format(y_train.shape))
print("驗(yàn)證集圖像大小:{}".format(x_valid.shape))
print("驗(yàn)證集標(biāo)簽大?。簕}".format(y_valid.shape))
print("測(cè)試集圖像大?。簕}".format(x_test.shape))
print("測(cè)試集標(biāo)簽大?。簕}".format(y_test.shape))

# 參數(shù)準(zhǔn)備
img_size = 28 * 28
num_classes = 10
learning_rate = 1e-4
epochs = 10
batch_size = 50

# 定義輸入占位符
x = tf.placeholder(tf.float32, shape=[None, img_size])
x_shaped = tf.reshape(x, [-1, 28, 28, 1])

# 定義輸出占位符
y = tf.placeholder(tf.float32, shape=[None, num_classes])

# 定義卷積函數(shù)
def create_conv2d(input_data, num_input_channels, num_filters, filter_shape, pool_shape, name):
    # 卷積的過(guò)濾器大小結(jié)構(gòu)是[filter_height, filter_width, in_channels, out_channels]
    conv_filter_shape = [filter_shape[0], filter_shape[1], num_input_channels, num_filters]
    
    # 定義權(quán)重Tensor變量,初始化時(shí)是截?cái)嗾龖B(tài)分布,標(biāo)準(zhǔn)差是0.03
    weights = tf.Variable(tf.truncated_normal(conv_filter_shape, stddev=0.03), name=name+"_W")
    
    # 定義偏移項(xiàng)Tensor變量,初始化時(shí)是截?cái)嗾龖B(tài)分布
    bias = tf.Variable(tf.truncated_normal([num_filters]), name=name+"_b")
    
    # 定義卷積層
    out_layer = tf.nn.conv2d(input_data, weights, (1, 1, 1, 1), padding="SAME")
    out_layer += bias
    # 通過(guò)激活函數(shù)ReLU來(lái)計(jì)算輸出
    out_layer = tf.nn.relu(out_layer)
    # 添加最大池化層
    out_layer = tf.nn.max_pool(out_layer, ksize=(1, pool_shape[0], pool_shape[1], 1), strides=(1, 2, 2, 1), padding="SAME")
    return out_layer

# 添加第一層卷積層
layer1 = create_conv2d(x_shaped, 1, 32, (5, 5), (2, 2), name="layer1")
# 添加第二層卷積層
layer2 = create_conv2d(layer1, 32, 64, (5, 5), (2, 2), name="layer2")
# 添加扁平化層
flattened = tf.reshape(layer2, (-1, 7 * 7 * 64))

# 添加全連接層
wd1 = tf.Variable(tf.truncated_normal((7 * 7 * 64, 1000), stddev=0.03), name="wd1")
bd1 = tf.Variable(tf.truncated_normal([1000], stddev=0.01), name="bd1")
dense_layer1 = tf.add(tf.matmul(flattened, wd1), bd1)
dense_layer1 = tf.nn.relu(dense_layer1)

# 添加輸出全連接層
wd2 = tf.Variable(tf.truncated_normal((1000, num_classes), stddev=0.03), name="wd2")
bd2 = tf.Variable(tf.truncated_normal([num_classes], stddev=0.01), name="bd2")
dense_layer2 = tf.add(tf.matmul(dense_layer1, wd2), bd2)

# 添加激活函數(shù)的softmax輸出層
y_ = tf.nn.softmax(dense_layer2)

# 通過(guò)softmax交叉熵定義計(jì)算損失值
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=y_, labels=y))
# 定義優(yōu)化器是Adam
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

# 定義預(yù)測(cè)結(jié)果的比較
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
# 定義預(yù)測(cè)的精確度
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

iteration = 0


import math

# 定義要保存訓(xùn)練模型的變量
saver = tf.train.Saver()

# 創(chuàng)建TensorFlow會(huì)話
with tf.Session() as sess:
  
    # 初始化TensorFlow的全局變量
    sess.run(tf.global_variables_initializer())
    
    # 計(jì)算所有的訓(xùn)練集需要被訓(xùn)練多少次,當(dāng)每批次是batch_size個(gè)時(shí)
    batch_count = int(math.ceil(x_train.shape[0] / float(batch_size)))
    
    # 要迭代epochs次訓(xùn)練
    for e in range(epochs):
        # 對(duì)每張圖像進(jìn)行訓(xùn)練
        for batch_i in range(batch_count):
            # 每次取出batch_size張圖像
            batch_x, batch_y = mnist.train.next_batch(batch_size=batch_size)
            # 訓(xùn)練模型
            _, loss = sess.run([optimizer, cost], feed_dict={x: batch_x, y: batch_y})
            
            # 每訓(xùn)練20次圖像時(shí)打印一次日志信息,也就是20次乘以batch_size個(gè)圖像已經(jīng)被訓(xùn)練了
            if batch_i % 20 == 0:
                print("Epoch: {}/{}".format(e+1, epochs), 
                      "Iteration: {}".format(iteration), 
                      "Training loss: {:.5f}".format(loss))
            iteration += 1
            
            # 每迭代一次時(shí),做一次驗(yàn)證,并打印日志信息
            if iteration % batch_size == 0:
                valid_acc = sess.run(accuracy, feed_dict={x: x_valid, y: y_valid})
                print("Epoch: {}/{}".format(e, epochs),
                      "Iteration: {}".format(iteration),
                      "Validation Accuracy: {:.5f}".format(valid_acc))

    # 保存模型的檢查點(diǎn)
    saver.save(sess, "checkpoints/mnist_cnn_tf.ckpt")

# 預(yù)測(cè)測(cè)試數(shù)據(jù)集
saver = tf.train.Saver()
with tf.Session() as sess:
    # 從TensorFlow會(huì)話中恢復(fù)之前保存的模型檢查點(diǎn)
    saver.restore(sess, tf.train.latest_checkpoint('checkpoints/'))
    
    # 通過(guò)測(cè)試集預(yù)測(cè)精確度
    test_acc = sess.run(accuracy, feed_dict={x: x_test, y: y_test})
    print("test accuracy: {:.5f}".format(test_acc))

Keras搭建MLP

import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation
from keras.optimizers import RMSprop

# 參數(shù)準(zhǔn)備
batch_size = 128
num_classes = 10
epochs = 20
img_size = 28 * 28

# 下載并讀取MNIST數(shù)據(jù)集數(shù)據(jù)
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# 分割驗(yàn)證集數(shù)據(jù)
valid_len = 5000
x_len = x_train.shape[0]
train_len = x_len-valid_len

# 驗(yàn)證集數(shù)據(jù)
x_valid = x_train[train_len:]
y_valid = y_train[train_len:]

# 訓(xùn)練集數(shù)據(jù)
x_train = x_train[:train_len]
y_train = y_train[:train_len]

# 將訓(xùn)練集、驗(yàn)證集和測(cè)試集數(shù)據(jù)進(jìn)行圖像向量轉(zhuǎn)換
x_train = x_train.reshape(x_train.shape[0], img_size)
x_valid = x_valid.reshape(x_valid.shape[0], img_size)
x_test = x_test.reshape(x_test.shape[0], img_size)

# 將訓(xùn)練集、驗(yàn)證集和測(cè)試集數(shù)據(jù)都轉(zhuǎn)換成float32類型
x_train = x_train.astype('float32')
x_valid = x_valid.astype('float32')
x_test = x_test.astype('float32')

# 將訓(xùn)練集、驗(yàn)證集和測(cè)試集數(shù)據(jù)都轉(zhuǎn)換成0到1之間的數(shù)值,就是歸一化處理
x_train /= 255
x_valid /= 255
x_test /= 255

# 通過(guò)to_categorical()函數(shù)將訓(xùn)練集標(biāo)簽、驗(yàn)證集標(biāo)簽和測(cè)試集標(biāo)簽獨(dú)熱編碼(one-hot encoding)
y_train = keras.utils.to_categorical(y_train, num_classes)
y_valid = keras.utils.to_categorical(y_valid, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

# 創(chuàng)建模型
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(img_size,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(num_classes, activation='softmax'))
# 模型架構(gòu)預(yù)覽
model.summary()

# 編譯模型
model.compile(loss='categorical_crossentropy', optimizer=RMSprop(), metrics=['accuracy'])
# 訓(xùn)練模型
model.fit(x_train, y_train, epochs=epochs, batch_size=batch_size, verbose=1, validation_data=(x_valid, y_valid))

# 評(píng)估模型
score = model.evaluate(x_test, y_test, verbose=0)
print('Test accuracy:{}, Test loss: {}, {}'.format(score[1], score[0], score))


#模型預(yù)測(cè),畫圖
import matplotlib.pyplot as plt
import numpy as np
x_img = x_test[7:8]
# 預(yù)測(cè)單張圖像的概率
prediction = model.predict(x_img)
x_coordinates = np.arange(prediction.shape[1])
plt.bar(x_coordinates, prediction[0][:])
plt.xticks(x_coordinates, np.arange(10))
plt.show()

Keras搭建CNN

import numpy as np
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D
from keras import utils

# 參數(shù)準(zhǔn)備
batch_size = 128
epochs = 15
num_classes = 10

img_width = 28
img_height = 28
img_channels = 1

# 下載并讀取MNIST數(shù)據(jù)集數(shù)據(jù)
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# 分割驗(yàn)證集數(shù)據(jù)
valid_len = 5000
x_len = x_train.shape[0]
train_len = x_len-valid_len

# 驗(yàn)證集數(shù)據(jù)
x_valid = x_train[train_len:]
y_valid = y_train[train_len:]

# 訓(xùn)練集數(shù)據(jù)
x_train = x_train[:train_len]
y_train = y_train[:train_len]

# 將訓(xùn)練集、驗(yàn)證集和測(cè)試集數(shù)據(jù)進(jìn)行圖像轉(zhuǎn)換,
# 圖像的形狀大小是 [batch, height, width, channels]
x_train = x_train.reshape(x_train.shape[0], img_height, img_width, img_channels)
x_valid = x_valid.reshape(x_valid.shape[0], img_height, img_width, img_channels)
x_test = x_test.reshape(x_test.shape[0], img_height, img_width, img_channels)

# 將訓(xùn)練集、驗(yàn)證集和測(cè)試集數(shù)據(jù)都轉(zhuǎn)換成float32類型
x_train = x_train.astype(np.float32)
x_valid = x_valid.astype(np.float32)
x_test = x_test.astype(np.float32)

# 將訓(xùn)練集、驗(yàn)證集和測(cè)試集數(shù)據(jù)都轉(zhuǎn)換成0到1之間的數(shù)值,就是歸一化處理
x_train /= 255
x_valid /= 255
x_test /= 255

# 通過(guò)to_categorical()函數(shù)將訓(xùn)練集標(biāo)簽、驗(yàn)證集標(biāo)簽和測(cè)試集標(biāo)簽獨(dú)熱編碼(one-hot encoding)
y_train = keras.utils.to_categorical(y_train, num_classes)
y_valid = keras.utils.to_categorical(y_valid, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

# 創(chuàng)建模型
model = Sequential()
model.add(Conv2D(filters=32, kernel_size=(3, 3), activation='relu', input_shape=(img_width, img_height, img_channels)))
model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
# 模型架構(gòu)預(yù)覽
model.summary()

# 編譯模型
model.compile(loss=keras.losses.categorical_crossentropy, 
              optimizer=keras.optimizers.Adadelta(), metrics=['accuracy'])

# 訓(xùn)練模型
model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, 
          verbose=1, validation_data=(x_valid, y_valid))

# 評(píng)估模型
score = model.evaluate(x_test, y_test, verbose=0)
print("Test Loss: {:.5f}, Test Accuracy: {:.5f}".format(score[0], score[1]))

# 單張圖像預(yù)測(cè)
import matplotlib.pyplot as plt

# 取出第一張圖像
x_img = x_test[0:1]
# 通過(guò)模型預(yù)測(cè)
prediction = model.predict(x_img)

# 繪制圖展示
x_coordinate = np.arange(prediction.shape[1])
plt.bar(x_coordinate, prediction[0][:])
plt.xticks(x_coordinate, np.arange(10))
plt.show()

print("預(yù)測(cè)的圖中的數(shù)字是{}。".format(y_test[0:1]))

狗的品種識(shí)別

狗狗圖片數(shù)據(jù):
鏈接:https://pan.baidu.com/s/1cEgg2aqXvAvI58M8EAS9CQ 密碼:8ahu

Keras搭建CNN

from sklearn.datasets import load_files       
from sklearn.model_selection import train_test_split
from keras.utils import np_utils
from keras.preprocessing import image   
import numpy as np
from glob import glob
import matplotlib.pyplot as plt
from matplotlib import image
import tqdm

# 共有120種狗狗的品種
num_classes = 120

# 定義加載數(shù)據(jù)集的函數(shù)
def load_dataset(path):
    # 通過(guò)sklearn提供的load_files()方法加載文件
    # 返回一個(gè)類字典對(duì)象,包含文件相對(duì)路徑和文件所屬編號(hào)
    data = load_files(path)
    # 將文件路徑轉(zhuǎn)變成NumPy對(duì)象
    dog_files = np.array(data['filenames'])
    # 狗狗的每張圖片都按照順序排成列表
    raw_targets = np.array(data['target'])
    # 通過(guò)to_categorical()方法將文件所屬編號(hào)轉(zhuǎn)換成二進(jìn)制類別矩陣(就是one-hot encoding)
    dog_targets = np_utils.to_categorical(raw_targets, num_classes)
    # 返回所有圖片文件路徑,圖片文件編號(hào)和圖片文件的二進(jìn)制類別矩陣
    return dog_files, raw_targets, dog_targets
  
# 加載數(shù)據(jù)集
dog_filepaths, dog_raw_targets, dog_targets = load_dataset('Images/')

# 加載狗狗的品種名稱列表
# glob是一個(gè)文件操作相關(guān)的模塊,通過(guò)指定的匹配模式,返回相應(yīng)的文件或文件夾路徑
# 這里的操作就是返回Images目錄下的所有文件夾
# 最后通過(guò)列表推導(dǎo)式遍歷每個(gè)文件路徑字符串,并截取狗狗類別名稱那段字符串
dogpath_prefix_len = len('Images/n02085620-')
dog_names = [item[dogpath_prefix_len:] for item in sorted(glob("Images/*"))]

print('狗狗的品種有{}種。'.format(len(dog_names)))
print('狗狗的圖片一共有{}張。n'.format(len(dog_filepaths)))


# 為了訓(xùn)練更快些,也考慮到一些讀者的本地機(jī)器性能不高,我們就用前9000張狗狗的圖片吧
# 如果讀者的機(jī)器性能還不錯(cuò),那就注釋這兩行,直接訓(xùn)練所有的圖片數(shù)據(jù)
dog_filepaths = dog_filepaths[:9000]
dog_targets = dog_targets[:9000]

# 分割訓(xùn)練數(shù)據(jù)集和測(cè)試數(shù)據(jù)集
X_train, X_test, y_train, y_test = train_test_split(dog_filepaths, dog_targets, test_size=0.2)

# 將測(cè)試集數(shù)據(jù)分割一半給驗(yàn)證集
half_test_count = int(len(X_test) / 2)
X_valid = X_test[:half_test_count]
y_valid = y_test[:half_test_count]

X_test = X_test[half_test_count:]
y_test = y_test[half_test_count:]

print("X_train.shape={}, y_train.shape={}.".format(X_train.shape, y_train.shape))
print("X_valid.shape={}, y_valid.shape={}.".format(X_valid.shape, y_valid.shape))
print("X_test.shape={}, y_test.shape={}.".format(X_test.shape, y_test.shape))

# 設(shè)置matplotlib在繪圖時(shí)的默認(rèn)樣式
plt.style.use('default')


# 查看隨機(jī)9張狗狗的圖像
def draw_random_9_dog_images():
    # 創(chuàng)建9個(gè)繪圖對(duì)象,3行3列
    fig, axes = plt.subplots(nrows=3, ncols=3)
    # 設(shè)置繪圖的總?cè)萜鞔笮?/span>
    fig.set_size_inches(10, 9)

    # 隨機(jī)選擇9個(gè)數(shù),也就是9個(gè)品種的狗(可能重復(fù),且每次都不一樣)
    random_9_nums = np.random.choice(len(X_train), 9)
    # 從訓(xùn)練集中選出9張圖
    random_9_imgs = X_train[random_9_nums]
    print(random_9_imgs)

    # 根據(jù)這隨機(jī)的9張圖片路徑,截取取得相應(yīng)的狗狗品種名稱
    imgname_list = []
    for imgpath in random_9_imgs:
        imgname = imgpath[dogpath_prefix_len:] 
        imgname = imgname[:imgname.find('/')]
        imgname_list.append(imgname)

    index = 0
    for row_index in range(3): # 行
        for col_index in range(3): # 列
            # 讀取圖片的數(shù)值內(nèi)容
            img = image.imread(random_9_imgs[index])
            # 獲取繪圖Axes對(duì)象,根據(jù)[行索引, 列索引]
            ax = axes[row_index, col_index]
            # 在Axes對(duì)象上顯示圖像
            ax.imshow(img)
            # 在繪圖對(duì)象上設(shè)置狗狗品種名稱
            ax.set_xlabel(imgname_list[index])
            # 索引加1
            index += 1
            
draw_random_9_dog_images()

# 對(duì)數(shù)據(jù)集進(jìn)行遍歷,讀取每張圖片,并獲取它的大小,
# 最后返回的圖片shape存儲(chǔ)在變量dogs_shape_list列表里
dogs_shape_list = []
for filepath in dog_filepaths:
    shape = image.imread(filepath).shape
    if len(shape) == 3:
        dogs_shape_list.append(shape)
             
dogs_shapes = np.asarray(dogs_shape_list)

print("總共{}張。".format(len(dogs_shapes)))
print("隨機(jī)抽取三張圖片的維度是{}。".format(dogs_shapes[np.random.choice(len(dogs_shapes), 3)]))

dogs_mean_width = np.mean(dogs_shapes[:,0])
dogs_mean_height = np.mean(dogs_shapes[:,1])
print("狗狗的圖片的平均寬:{:.1f} * 平均高:{:.1f}。".format(dogs_mean_width, dogs_mean_height))

# 定義一個(gè)函數(shù),將每張圖片都轉(zhuǎn)換成標(biāo)準(zhǔn)大小(1, 224, 224, 3)
def path_to_tensor(img_path):
    # 加載圖片
    # 圖片對(duì)象的加載用的是PIL庫(kù),通過(guò)load_img()方法返回的就是一個(gè)PIL對(duì)象
    img = image.load_img(img_path, target_size=(224, 224, 3))
    # 將PIL圖片對(duì)象類型轉(zhuǎn)化為格式(224, 224, 3)的3維張量
    x = image.img_to_array(img)
    # 將3維張量轉(zhuǎn)化格式為(1, 224, 224, 3)的4維張量并返回
    return np.expand_dims(x, axis=0)

# 定義一個(gè)函數(shù),將數(shù)組里的所有路徑的圖片都轉(zhuǎn)換成圖像數(shù)值類型并返回
def paths_to_tensor(img_paths):
    # tqdm模塊表示使用進(jìn)度條顯示,傳入一個(gè)所有圖片的數(shù)組對(duì)象
    # 將所有圖片的對(duì)象一個(gè)個(gè)都轉(zhuǎn)換成numpy數(shù)值對(duì)象張量后,并返回成數(shù)組
    list_of_tensors = [path_to_tensor(img_path) for img_path in tqdm(img_paths)]
    # 將對(duì)象垂直堆砌排序擺放
    return np.vstack(list_of_tensors)


from PIL import ImageFile 
# 為了防止PIL讀取圖片對(duì)象時(shí)出現(xiàn)IO錯(cuò)誤,則設(shè)置截?cái)鄨D片為True
ImageFile.LOAD_TRUNCATED_IMAGES = True                 

# 將所有圖片都轉(zhuǎn)換成標(biāo)準(zhǔn)大小的數(shù)值圖像對(duì)象,然后除以255,進(jìn)行歸一化處理
# RGB的顏色值,最大為255,最小為0
# 對(duì)訓(xùn)練集數(shù)據(jù)進(jìn)行處理
train_tensors = paths_to_tensor(X_train).astype(np.float32) / 255
# 對(duì)驗(yàn)證集數(shù)據(jù)進(jìn)行處理
valid_tensors = paths_to_tensor(X_valid).astype(np.float32) / 255
# 對(duì)測(cè)試集數(shù)據(jù)進(jìn)行處理
test_tensors = paths_to_tensor(X_test).astype(np.float32) / 255


from keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D
from keras.layers import Dropout, Flatten, Dense
from keras.models import Sequential

# 創(chuàng)建Sequential模型
model = Sequential()

# 創(chuàng)建輸入層,輸入層必須傳入input_shape參數(shù)以表示圖像大小,深度是16
model.add(Conv2D(filters=16, kernel_size=(2, 2), strides=(1, 1), padding='same', 
                 activation='relu', input_shape=train_tensors.shape[1:]))
# 添加最大池化層,大小為2x2,有效范圍默認(rèn)是valid,就是說(shuō),不夠2x2的大小的空間數(shù)據(jù)就丟棄了
model.add(MaxPooling2D(pool_size=(2, 2)))
# 添加Dropout層,每次丟棄20%的網(wǎng)絡(luò)節(jié)點(diǎn),防止過(guò)擬合
model.add(Dropout(0.2))

# 添加卷積層,深度是32,內(nèi)核大小是2x2,跨步是1x1,有效范圍是same則表示不夠數(shù)據(jù)范圍的就用0填充
model.add(Conv2D(filters=32, kernel_size=(2, 2), strides=(1, 1), padding='same', activation='relu'))
# 添加最大池化層,大小為2x2,有效范圍默認(rèn)是valid,就是說(shuō),不夠2x2的大小的空間數(shù)據(jù)就丟棄了
model.add(MaxPooling2D(pool_size=(2, 2)))
# 添加Dropout層,每次丟棄20%的網(wǎng)絡(luò)節(jié)點(diǎn),防止過(guò)擬合
model.add(Dropout(0.2))

# 添加卷積層,深度是64
model.add(Conv2D(filters=64, kernel_size=(2, 2), strides=(1, 1), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))

# 添加全局平均池化層
model.add(GlobalAveragePooling2D())
# 添加Dropout,每次丟棄50%
model.add(Dropout(0.5))
# 添加輸出層,120個(gè)類別輸出
model.add(Dense(num_classes, activation="softmax"))
                 
# 打印輸出網(wǎng)絡(luò)模型架構(gòu)
model.summary()

# 編譯模型
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

from keras.callbacks import ModelCheckpoint 

epochs = 20
checkpointer = ModelCheckpoint(filepath='saved_models/weights.best.from_scratch.hdf5', 
                               verbose=1, 
                               save_best_only=True)

model.fit(train_tensors, 
          y_train, 
          validation_data=(valid_tensors, y_valid),
          epochs=epochs, 
          batch_size=20, 
          callbacks=[checkpointer], 
          verbose=1)

## 加載具有最好驗(yàn)證權(quán)重的模型
model.load_weights('saved_models/weights.best.from_scratch.hdf5')

# 獲取測(cè)試數(shù)據(jù)集中每一個(gè)圖像所預(yù)測(cè)的狗品種的index
dog_breed_predictions = [np.argmax(model.predict(np.expand_dims(tensor, axis=0))) for tensor in test_tensors]

# 測(cè)試準(zhǔn)確率
test_accuracy = 100*np.sum(np.array(dog_breed_predictions)==np.argmax(y_test, axis=1))/len(dog_breed_predictions)
print('Test Accuracy: {:.4f}'.format(test_accuracy))

#結(jié)果發(fā)現(xiàn)準(zhǔn)確率很低很低,這是我們需要遷移學(xué)習(xí)

遷移學(xué)習(xí)(InceptionV3)


# 導(dǎo)入InceptionV3預(yù)訓(xùn)練模型和數(shù)據(jù)處理模塊
from keras.applications.inception_v3 import InceptionV3, preprocess_input, decode_predictions
# 導(dǎo)入構(gòu)建Keras的Model所需模塊
from keras.models import Model
from keras.layers import Dense, GlobalAveragePooling2D, Dropout
from keras.preprocessing import image
from keras.optimizers import SGD
from keras.callbacks import ModelCheckpoint  
# 導(dǎo)入圖片數(shù)據(jù)增強(qiáng)生成器
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt


class InceptionV3Retrained:
    """
    定義一個(gè)類,用來(lái)在預(yù)訓(xùn)練模型上去訓(xùn)練新的數(shù)據(jù)
    """
    

    def add_new_last_layers(self, base_model, num_classes):
        """
        添加新的全連接層
        """
        # 添加一個(gè)全局空間平均池化層
        x = base_model.output
        x = GlobalAveragePooling2D()(x)

        # 添加1024個(gè)全連接層
        x = Dense(1024, activation='relu')(x)

        # 添加全連接輸出層,有num_classes個(gè)類別輸出,使用softmax多類別分類激活函數(shù)
        predictions = Dense(num_classes, activation='softmax')(x)

        # 通過(guò)上面定義的base_model對(duì)象和它的輸出層
        # 我們自定義創(chuàng)建一個(gè)新的Keras的Model模型對(duì)象
        model = Model(input=base_model.input, output=predictions)
        return model


    def freeze_previous_layers(self, model, base_model):
        """
        凍結(jié)預(yù)訓(xùn)練模型之前的層
        """
        # 凍結(jié)InceptionV3模型的所有卷積層,因?yàn)槲覀冞w移學(xué)習(xí)就是對(duì)頂部的幾個(gè)層進(jìn)行訓(xùn)練
        for layer in base_model.layers:
            layer.trainable = False

        # 編譯模型
        # 優(yōu)化器rmsprop,參數(shù)使用默認(rèn)值即可
        # 分類交叉熵使用多類別的
        model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])


    def fine_tune_model(self, model):
        """
        微調(diào)模型
        """
        # 我們凍結(jié)模型的前面172層,然后把剩下的層數(shù)都解凍
        for layer in model.layers[:172]:
            layer.trainable = False
        for layer in model.layers[172:]:
            layer.trainable = True

        # 再編譯模型
        # 優(yōu)化器使用隨機(jī)梯度下降,學(xué)習(xí)率我們調(diào)小點(diǎn)0.0001
        # 分類交叉熵依舊使用多類別的
        model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='categorical_crossentropy', metrics=['accuracy'])
  
  
    def plot_training(self, history):
        """
        繪制訓(xùn)練模型時(shí)的損失值和精確度
        """
        # 取出訓(xùn)練時(shí)的精確度
        acc = history.history['acc']
        # 取出驗(yàn)證時(shí)的精確度
        val_acc = history.history['val_acc']
        # 取出訓(xùn)練時(shí)的損失值
        loss = history.history['loss']
        # 取出驗(yàn)證時(shí)的損失值
        val_loss = history.history['val_loss']
        # 根據(jù)精確度的個(gè)數(shù),就可以得知訓(xùn)練了多少次
        epochs = range(len(acc))

        # 繪制訓(xùn)練精確度和驗(yàn)證精確度
        plt.plot(epochs, acc, 'r.')
        plt.plot(epochs, val_acc, 'r')
        plt.title('Training and validation accuracy')

        # 繪制訓(xùn)練損失和驗(yàn)證損失
        plt.figure()
        plt.plot(epochs, loss, 'r.')
        plt.plot(epochs, val_loss, 'r-')
        plt.title('Training and validation loss')
        plt.show()


    def train(self, num_classes, batch_size, epochs):
        """
        訓(xùn)練模型
        """

        # 定義訓(xùn)練數(shù)據(jù)增強(qiáng)生成器
        # 參數(shù)preprocessing_function表示每次輸入都進(jìn)行預(yù)處理
        # 參數(shù)rotation_range表示圖像隨機(jī)旋轉(zhuǎn)的度數(shù)范圍
        # 參數(shù)width_shift_range表示圖像的寬度可移動(dòng)范圍
        # 參數(shù)height_shift_range表示圖像的高度可移動(dòng)范圍
        # 參數(shù)shear_range表示逆時(shí)針?lè)较蚣羟薪嵌?/span>
        # 參數(shù)zoom_range表示隨機(jī)縮放的角度值
        # 參數(shù)horizontal_flip表示是否水平翻轉(zhuǎn)
        train_datagen = ImageDataGenerator(
          preprocessing_function=preprocess_input,
          rotation_range=20,
          width_shift_range=0.2,
          height_shift_range=0.2,
          shear_range=0.2,
          zoom_range=0.2,
          horizontal_flip=True
        )
        
        # 定義驗(yàn)證數(shù)據(jù)增強(qiáng)生成器
        valid_datagen = ImageDataGenerator(
          preprocessing_function=preprocess_input,
          rotation_range=20,
          width_shift_range=0.2,
          height_shift_range=0.2,
          shear_range=0.2,
          zoom_range=0.2,
          horizontal_flip=True
        )

        # 訓(xùn)練數(shù)據(jù)增強(qiáng)
        train_generator = train_datagen.flow(train_tensors, y_train, batch_size=batch_size)
        # 驗(yàn)證數(shù)據(jù)增強(qiáng)
        validation_generator = valid_datagen.flow(valid_tensors, y_valid, batch_size=batch_size)

        # 初始化InceptionV3模型
        # include_top=False表示初始化模型時(shí)不包含InceptionV3網(wǎng)絡(luò)結(jié)構(gòu)層中的最后的全連接層
        base_model = InceptionV3(weights='imagenet', include_top=False)  
        
        # 添加新的全連接層
        model = self.add_new_last_layers(base_model, num_classes)

        # 凍結(jié)剛創(chuàng)建的InceptionV3的模型的所有卷積層
        self.freeze_previous_layers(model, base_model)
        
        # 定義模型檢查點(diǎn),只保存最佳的
        checkpointer = ModelCheckpoint(filepath='inception_v3.dogs.133.best.weights.h5', 
                                       verbose=1, 
                                       save_best_only=True)

        print("首次訓(xùn)練模型")
        # 在新數(shù)據(jù)集上訓(xùn)練模型
        history_tl = model.fit_generator(train_generator, 
                          steps_per_epoch=train_tensors.shape[0] / batch_size, 
                          validation_steps=valid_tensors.shape[0] / batch_size, 
                          epochs=epochs,
                          verbose=1, 
                          callbacks=[checkpointer], 
                          validation_data=validation_generator)

        # 微調(diào)模型
        self.fine_tune_model(model)

        print("微調(diào)模型后,再次訓(xùn)練模型")
        # 我們?cè)俅斡?xùn)練模型
        history_ft = model.fit_generator(train_generator, 
                          steps_per_epoch=train_tensors.shape[0] / batch_size, 
                          validation_steps=valid_tensors.shape[0] / batch_size,
                          epochs=epochs,
                          verbose=1, 
                          callbacks=[checkpointer], 
                          validation_data=validation_generator)

        # 繪制模型的損失值和精確度
        self.plot_training(history_ft)

# 每批次大小是128
batch_size = 128
# 訓(xùn)練5個(gè)批次
epochs = 5

incepV3_model = InceptionV3Retrained()
incepV3_model.train(num_classes, batch_size, epochs)


# 測(cè)試模型的精確度
# 創(chuàng)建一個(gè)不帶全連接層的InceptionV3模型
test_model = InceptionV3(weights='imagenet', include_top=False, input_shape=test_tensors.shape[1:]) 

# 添加全連接層輸出層
incepV3_model = InceptionV3Retrained()
trained_model = incepV3_model.add_new_last_layers(test_model, num_classes)

# 加載剛才訓(xùn)練的權(quán)重到模型中
trained_model.load_weights("inception_v3.dogs.133.best.weights.h5") 

# 編譯模型
trained_model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])

# 通過(guò)summary()方法,可以看到完整的InceptionV3的神經(jīng)網(wǎng)絡(luò)模型架構(gòu)
# trained_model.summary()

# 評(píng)估模型
score = trained_model.evaluate(test_tensors, y_test, verbose=1)
print("Test {}: {:.2f}. Test {}: {:.2f}.".format(trained_model.metrics_names[0], 
                                                 score[0]*100, 
                                                 trained_model.metrics_names[1], 
                                                 score[1]*100))

# 預(yù)測(cè)狗狗品種
def predict_dog_breed(model, img_path):
    # 加載圖像
    x = load_img(img_path)
    # 圖片預(yù)處理
    x = preprocess_input(x)
    # 模型預(yù)測(cè)
    predictions = model.predict(x)
    # 取出預(yù)測(cè)數(shù)值
    prediction_list = predictions[0]

    # 取出最大值索引和最大值
    def get_max_arg_value(prediction_list):
        arg_max = np.argmax(prediction_list)
        max_val = prediction_list[arg_max]
        preds = np.delete(prediction_list, arg_max)
        return preds, arg_max, max_val

    # 取出前3個(gè)預(yù)測(cè)值的最大值索引和最大值
    def get_list_of_max_arg_value(prediction_list):
        preds, argmax1, max1val = get_max_arg_value(prediction_list)
        preds, argmax2, max2val = get_max_arg_value(preds)
        preds, argmax3, max3val = get_max_arg_value(preds)

        top_3_argmax = np.array([argmax1, argmax2, argmax3])
        top_3_max_val = np.array([max1val, max2val, max3val])
        return top_3_argmax, top_3_max_val

    top_3_argmax, top_3_max_val = get_list_of_max_arg_value(prediction_list)
    dog_titles = [dog_names[index] for index in top_3_argmax]

    print('前3個(gè)最大值: {}'.format(top_3_max_val))

#     # 如果希望顯示直方圖,可以取消注釋這三行代碼
#     plt.barh(np.arange(3), top_3_max_val)
#     plt.yticks(np.arange(3), dog_titles)
#     plt.show()
    
    # 創(chuàng)建繪圖對(duì)象
    fig, ax = plt.subplots()
    # 設(shè)置繪圖的總?cè)萜鞔笮?/span>
    fig.set_size_inches(5, 5)
    # 將最大值乘以100就是百分比
    top_3_max_val *= 100
    # 拼接前三個(gè)最大值的字符串
    dog_title = "{}: {:.2f}%n".format(dog_titles[0], top_3_max_val[0]) + 
                "{}: {:.2f}%n".format(dog_titles[1], top_3_max_val[1]) + 
                "{}: {:.2f}%n".format(dog_titles[2], top_3_max_val[2])
    # 在繪圖的右上角顯示加上識(shí)別的值字符串
    ax.text(1.01, 0.8, 
            dog_title, 
            horizontalalignment='left', 
            verticalalignment='bottom',
            transform=ax.transAxes)
    # 讀取圖片的數(shù)值內(nèi)容
    img = matplotlib.image.imread(img_path)
    # 在Axes對(duì)象上顯示圖像
    ax.imshow(img)

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
LAN8710AI-EZK-TR 1 Microchip Technology Inc DATACOM, ETHERNET TRANSCEIVER, QCC32, 5 X 5 MM, 0.90 MM HEIGHT, ROHS COMPLIANT, QFN-32

ECAD模型

下載ECAD模型
$1.56 查看
TJA1040T/CM,118 1 NXP Semiconductors TJA1040 - High-speed CAN transceiver with standby mode SOIC 8-Pin

ECAD模型

下載ECAD模型
$2.24 查看
VOD217T 1 Vishay Intertechnologies VOD205T, VOD206T, VOD207T, VOD211T, VOD213T, VOD217T Optocoupler, Phototransistor Output, Dual Channel, SOIC-8 Package

ECAD模型

下載ECAD模型
$0.76 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜