python神經(jīng)網(wǎng)絡(luò)InceptionV3模型復(fù)現(xiàn)詳解
學(xué)習(xí)前言
Inception系列的結(jié)構(gòu)和其它的前向神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)不太一樣,每一層的內(nèi)容不是直直向下的,而是分了很多的塊
什么是InceptionV3模型
InceptionV3模型是谷歌Inception系列里面的第三代模型,其模型結(jié)構(gòu)與InceptionV2模型放在了同一篇論文里,其實(shí)二者模型結(jié)構(gòu)差距不大,相比于其它神經(jīng)網(wǎng)絡(luò)模型,Inception網(wǎng)絡(luò)最大的特
點(diǎn)在于將神經(jīng)網(wǎng)絡(luò)層與層之間的卷積運(yùn)算進(jìn)行了拓展。
如VGG,AlexNet網(wǎng)絡(luò),它就是一直卷積下來(lái)的,一層接著一層;
ResNet則是創(chuàng)新性的引入了殘差網(wǎng)絡(luò)的概念,使得靠前若干層的某一層數(shù)據(jù)輸出直接跳過(guò)多層引入到后面數(shù)據(jù)層的輸入部分,后面的特征層的內(nèi)容會(huì)有一部分由其前面的某一層線性貢獻(xiàn)。
而Inception網(wǎng)絡(luò)則是采用不同大小的卷積核,使得存在不同大小的感受野,最后實(shí)現(xiàn)拼接達(dá)到不同尺度特征的融合。
對(duì)于InceptionV3而言,其網(wǎng)絡(luò)中存在著如下的結(jié)構(gòu)。
這個(gè)結(jié)構(gòu)使用不同大小的卷積核對(duì)輸入進(jìn)行卷積(這個(gè)結(jié)構(gòu)主要在代碼中的block1使用)。
還存在著這樣的結(jié)構(gòu),利用1x7的卷積和7x1的卷積代替7x7的卷積,這樣可以只使用約(1x7 + 7x1) / (7x7) = 28.6%的計(jì)算開(kāi)銷;
利用1x3的卷積和3x1的卷積代替3x3的卷積,這樣可以只使用約(1x3 + 3x1) / (3x3) = 67%的計(jì)算開(kāi)銷。
下圖利用1x7的卷積和7x1的卷積代替7x7的卷積(這個(gè)結(jié)構(gòu)主要在代碼中的block2使用)。
下圖利用1x3的卷積和3x1的卷積代替3x3的卷積(這個(gè)結(jié)構(gòu)主要在代碼中的block3使用)。
InceptionV3網(wǎng)絡(luò)部分實(shí)現(xiàn)代碼
我一共將InceptionV3劃分為3個(gè)block,對(duì)應(yīng)著35x35、17x17,8x8維度大小的圖像。每個(gè)block中間有許多的part,對(duì)應(yīng)著不同的特征層深度,用于特征提取。
#-------------------------------------------------------------# # InceptionV3的網(wǎng)絡(luò)部分 #-------------------------------------------------------------# from __future__ import print_function from __future__ import absolute_import import warnings import numpy as np from keras.models import Model from keras import layers from keras.layers import Activation,Dense,Input,BatchNormalization,Conv2D,MaxPooling2D,AveragePooling2D from keras.layers import GlobalAveragePooling2D,GlobalMaxPooling2D from keras.engine.topology import get_source_inputs from keras.utils.layer_utils import convert_all_kernels_in_model from keras.utils.data_utils import get_file from keras import backend as K from keras.applications.imagenet_utils import decode_predictions from keras.preprocessing import image def conv2d_bn(x, filters, num_row, num_col, padding='same', strides=(1, 1), name=None): if name is not None: bn_name = name + '_bn' conv_name = name + '_conv' else: bn_name = None conv_name = None x = Conv2D( filters, (num_row, num_col), strides=strides, padding=padding, use_bias=False, name=conv_name)(x) x = BatchNormalization(scale=False, name=bn_name)(x) x = Activation('relu', name=name)(x) return x def InceptionV3(input_shape=[299,299,3], classes=1000): img_input = Input(shape=input_shape) x = conv2d_bn(img_input, 32, 3, 3, strides=(2, 2), padding='valid') x = conv2d_bn(x, 32, 3, 3, padding='valid') x = conv2d_bn(x, 64, 3, 3) x = MaxPooling2D((3, 3), strides=(2, 2))(x) x = conv2d_bn(x, 80, 1, 1, padding='valid') x = conv2d_bn(x, 192, 3, 3, padding='valid') x = MaxPooling2D((3, 3), strides=(2, 2))(x) #--------------------------------# # Block1 35x35 #--------------------------------# # Block1 part1 # 35 x 35 x 192 -> 35 x 35 x 256 branch1x1 = conv2d_bn(x, 64, 1, 1) branch5x5 = conv2d_bn(x, 48, 1, 1) branch5x5 = conv2d_bn(branch5x5, 64, 5, 5) branch3x3dbl = conv2d_bn(x, 64, 1, 1) branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3) branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3) branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x) branch_pool = conv2d_bn(branch_pool, 32, 1, 1) x = layers.concatenate( [branch1x1, branch5x5, branch3x3dbl, branch_pool], axis=3, name='mixed0') # Block1 part2 # 35 x 35 x 256 -> 35 x 35 x 288 branch1x1 = conv2d_bn(x, 64, 1, 1) branch5x5 = conv2d_bn(x, 48, 1, 1) branch5x5 = conv2d_bn(branch5x5, 64, 5, 5) branch3x3dbl = conv2d_bn(x, 64, 1, 1) branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3) branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3) branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x) branch_pool = conv2d_bn(branch_pool, 64, 1, 1) x = layers.concatenate( [branch1x1, branch5x5, branch3x3dbl, branch_pool], axis=3, name='mixed1') # Block1 part3 # 35 x 35 x 288 -> 35 x 35 x 288 branch1x1 = conv2d_bn(x, 64, 1, 1) branch5x5 = conv2d_bn(x, 48, 1, 1) branch5x5 = conv2d_bn(branch5x5, 64, 5, 5) branch3x3dbl = conv2d_bn(x, 64, 1, 1) branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3) branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3) branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x) branch_pool = conv2d_bn(branch_pool, 64, 1, 1) x = layers.concatenate( [branch1x1, branch5x5, branch3x3dbl, branch_pool], axis=3, name='mixed2') #--------------------------------# # Block2 17x17 #--------------------------------# # Block2 part1 # 35 x 35 x 288 -> 17 x 17 x 768 branch3x3 = conv2d_bn(x, 384, 3, 3, strides=(2, 2), padding='valid') branch3x3dbl = conv2d_bn(x, 64, 1, 1) branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3) branch3x3dbl = conv2d_bn( branch3x3dbl, 96, 3, 3, strides=(2, 2), padding='valid') branch_pool = MaxPooling2D((3, 3), strides=(2, 2))(x) x = layers.concatenate( [branch3x3, branch3x3dbl, branch_pool], axis=3, name='mixed3') # Block2 part2 # 17 x 17 x 768 -> 17 x 17 x 768 branch1x1 = conv2d_bn(x, 192, 1, 1) branch7x7 = conv2d_bn(x, 128, 1, 1) branch7x7 = conv2d_bn(branch7x7, 128, 1, 7) branch7x7 = conv2d_bn(branch7x7, 192, 7, 1) branch7x7dbl = conv2d_bn(x, 128, 1, 1) branch7x7dbl = conv2d_bn(branch7x7dbl, 128, 7, 1) branch7x7dbl = conv2d_bn(branch7x7dbl, 128, 1, 7) branch7x7dbl = conv2d_bn(branch7x7dbl, 128, 7, 1) branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7) branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x) branch_pool = conv2d_bn(branch_pool, 192, 1, 1) x = layers.concatenate( [branch1x1, branch7x7, branch7x7dbl, branch_pool], axis=3, name='mixed4') # Block2 part3 and part4 # 17 x 17 x 768 -> 17 x 17 x 768 -> 17 x 17 x 768 for i in range(2): branch1x1 = conv2d_bn(x, 192, 1, 1) branch7x7 = conv2d_bn(x, 160, 1, 1) branch7x7 = conv2d_bn(branch7x7, 160, 1, 7) branch7x7 = conv2d_bn(branch7x7, 192, 7, 1) branch7x7dbl = conv2d_bn(x, 160, 1, 1) branch7x7dbl = conv2d_bn(branch7x7dbl, 160, 7, 1) branch7x7dbl = conv2d_bn(branch7x7dbl, 160, 1, 7) branch7x7dbl = conv2d_bn(branch7x7dbl, 160, 7, 1) branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7) branch_pool = AveragePooling2D( (3, 3), strides=(1, 1), padding='same')(x) branch_pool = conv2d_bn(branch_pool, 192, 1, 1) x = layers.concatenate( [branch1x1, branch7x7, branch7x7dbl, branch_pool], axis=3, name='mixed' + str(5 + i)) # Block2 part5 # 17 x 17 x 768 -> 17 x 17 x 768 branch1x1 = conv2d_bn(x, 192, 1, 1) branch7x7 = conv2d_bn(x, 192, 1, 1) branch7x7 = conv2d_bn(branch7x7, 192, 1, 7) branch7x7 = conv2d_bn(branch7x7, 192, 7, 1) branch7x7dbl = conv2d_bn(x, 192, 1, 1) branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 7, 1) branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7) branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 7, 1) branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7) branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x) branch_pool = conv2d_bn(branch_pool, 192, 1, 1) x = layers.concatenate( [branch1x1, branch7x7, branch7x7dbl, branch_pool], axis=3, name='mixed7') #--------------------------------# # Block3 8x8 #--------------------------------# # Block3 part1 # 17 x 17 x 768 -> 8 x 8 x 1280 branch3x3 = conv2d_bn(x, 192, 1, 1) branch3x3 = conv2d_bn(branch3x3, 320, 3, 3, strides=(2, 2), padding='valid') branch7x7x3 = conv2d_bn(x, 192, 1, 1) branch7x7x3 = conv2d_bn(branch7x7x3, 192, 1, 7) branch7x7x3 = conv2d_bn(branch7x7x3, 192, 7, 1) branch7x7x3 = conv2d_bn( branch7x7x3, 192, 3, 3, strides=(2, 2), padding='valid') branch_pool = MaxPooling2D((3, 3), strides=(2, 2))(x) x = layers.concatenate( [branch3x3, branch7x7x3, branch_pool], axis=3, name='mixed8') # Block3 part2 part3 # 8 x 8 x 1280 -> 8 x 8 x 2048 -> 8 x 8 x 2048 for i in range(2): branch1x1 = conv2d_bn(x, 320, 1, 1) branch3x3 = conv2d_bn(x, 384, 1, 1) branch3x3_1 = conv2d_bn(branch3x3, 384, 1, 3) branch3x3_2 = conv2d_bn(branch3x3, 384, 3, 1) branch3x3 = layers.concatenate( [branch3x3_1, branch3x3_2], axis=3, name='mixed9_' + str(i)) branch3x3dbl = conv2d_bn(x, 448, 1, 1) branch3x3dbl = conv2d_bn(branch3x3dbl, 384, 3, 3) branch3x3dbl_1 = conv2d_bn(branch3x3dbl, 384, 1, 3) branch3x3dbl_2 = conv2d_bn(branch3x3dbl, 384, 3, 1) branch3x3dbl = layers.concatenate( [branch3x3dbl_1, branch3x3dbl_2], axis=3) branch_pool = AveragePooling2D( (3, 3), strides=(1, 1), padding='same')(x) branch_pool = conv2d_bn(branch_pool, 192, 1, 1) x = layers.concatenate( [branch1x1, branch3x3, branch3x3dbl, branch_pool], axis=3, name='mixed' + str(9 + i)) # 平均池化后全連接。 x = GlobalAveragePooling2D(name='avg_pool')(x) x = Dense(classes, activation='softmax', name='predictions')(x) inputs = img_input model = Model(inputs, x, name='inception_v3') return model
圖片預(yù)測(cè)
建立網(wǎng)絡(luò)后,可以用以下的代碼進(jìn)行預(yù)測(cè)。
def preprocess_input(x): x /= 255. x -= 0.5 x *= 2. return x if __name__ == '__main__': model = InceptionV3() model.load_weights("inception_v3_weights_tf_dim_ordering_tf_kernels.h5") img_path = 'elephant.jpg' img = image.load_img(img_path, target_size=(299, 299)) x = image.img_to_array(img) x = np.expand_dims(x, axis=0) x = preprocess_input(x) preds = model.predict(x) print('Predicted:', decode_predictions(preds))
預(yù)測(cè)所需的已經(jīng)訓(xùn)練好的InceptionV3模型可以在github下載非常方便。
預(yù)測(cè)結(jié)果為:
Predicted: [[('n02504458', 'African_elephant', 0.50874853), ('n01871265', 'tusker', 0.19524273), ('n02504013', 'Indian_elephant', 0.1566972), ('n01917289', 'brain_coral', 0.0008956835), ('n01695060', 'Komodo_dragon', 0.0008260256)]]
這里我推薦一個(gè)很不錯(cuò)的講InceptionV3結(jié)構(gòu)的深度神經(jīng)網(wǎng)絡(luò)Google Inception Net-V3結(jié)構(gòu)圖里面有每一層的結(jié)構(gòu)圖,非常清晰。
以上就是python神經(jīng)網(wǎng)絡(luò)InceptionV3模型復(fù)現(xiàn)詳解的詳細(xì)內(nèi)容,更多關(guān)于python神經(jīng)網(wǎng)絡(luò)InceptionV3模型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python實(shí)現(xiàn)登陸文件驗(yàn)證方法
本篇文章中我們給大家分享了關(guān)于Python實(shí)現(xiàn)登陸文件驗(yàn)證的方法和技巧,有興趣的朋友們參考學(xué)習(xí)下。2018-10-10python2利用wxpython生成投影界面工具的圖文詳解
這篇文章主要介紹了python2利用wxpython生成投影界面工具的圖文詳解,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04Python3 venv搭建輕量級(jí)虛擬環(huán)境的步驟(圖文)
這篇文章主要介紹了Python3 venv搭建輕量級(jí)虛擬環(huán)境的步驟(圖文),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Python PaddlePaddle機(jī)器學(xué)習(xí)之求解線性模型
這篇文章主要介紹了Python PaddlePaddle機(jī)器學(xué)習(xí)之求解線性模型,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定參考價(jià)值,需要的小伙伴可以參考一下2022-08-08Pycharm中無(wú)法使用pip安裝的包問(wèn)題解決方案
本文主要介紹了Pycharm中無(wú)法使用pip安裝的包問(wèn)題解決方案,在終端通過(guò)pip裝好包以后,在pycharm中導(dǎo)入包時(shí),依然會(huì)報(bào)錯(cuò),下面就來(lái)介紹一下解決方法2023-09-09Python使用低通濾波器模糊圖像功能實(shí)現(xiàn)
這篇文章主要介紹了Python使用低通濾波器模糊圖像,我們介紹了多種不同類型的濾波器核與卷積操作,使用 scipy.ndimage 模塊中的濾波器模糊圖像,利用 scipy.fftpack 模塊的 fft2() 函數(shù)實(shí)現(xiàn)高斯模糊,介紹了scipy.signal模塊的彩色圖像頻域卷積,需要的朋友可以參考下2023-03-03python實(shí)現(xiàn)DNS正向查詢、反向查詢的例子
這篇文章主要介紹了python實(shí)現(xiàn)DNS正向查詢、反向查詢的例子,需要的朋友可以參考下2014-04-04python實(shí)現(xiàn)json文件的增刪改操作方法
這篇文章主要介紹了python實(shí)現(xiàn)json文件的增刪改操作,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06Python Dict找出value大于某值或key大于某值的所有項(xiàng)方式
這篇文章主要介紹了Python Dict找出value大于某值或key大于某值的所有項(xiàng)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06Python如何使用struct.unpack處理二進(jìn)制文件
這篇文章主要介紹了Python如何使用struct.unpack處理二進(jìn)制文件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02