Keras fine-tuning (基於ImageNet上訓練好的模型,複用)

模型文件點這裏下載python

https://github.com/fchollet/deep-learning-modelsgit

權重文件點這裏下載github

https://github.com/fchollet/deep-learning-models/releases
json

下載好文件以後只須要在文件中將本來要從網絡上下載的語句註釋掉,文件路徑換成本身下載好的權重文件。數組

#WEIGHTS_PATH = 'D:/C/pythonEX/VGG16/vgg16_weights_tf_dim_ordering_tf_kernels.h5'
#WEIGHTS_PATH_NO_TOP = 'D:/C/pythonEX/VGG16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'

if weights == 'imagenet':
        if include_top:
            weights_path = 'D:/C/pythonEX/VGG16/vgg16_weights_tf_dim_ordering_tf_kernels.h5'
        else:
            weights_path = 'D:/C/pythonEX/VGG16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'
        
        model.load_weights(weights_path)

其餘的部分不變,要作fine-tuning的話,不要加載最後的全鏈接層,本身在輸出層上從新定義網絡。網絡

完整代碼:app

from __future__ import print_function
import numpy as np
import warnings

from keras.models import Model
from keras.layers import Flatten
from keras.layers import Dense
from keras.layers import Input
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import GlobalMaxPooling2D
from keras.layers import GlobalAveragePooling2D
from keras.preprocessing import image
from keras.utils import layer_utils
from keras.utils.data_utils import get_file
from keras import backend as K
from keras.applications.imagenet_utils import decode_predictions
# decode_predictions 輸出5個最高几率:(類名, 語義概念, 預測機率) decode_predictions(y_pred)
from keras.applications.imagenet_utils import preprocess_input
#  預處理 圖像編碼服從規定,譬如,RGB,GBR這一類的,preprocess_input(x)  
from keras.applications.imagenet_utils import _obtain_input_shape
# 肯定適當的輸入形狀,至關於opencv中的read.img,將圖像變爲數組
from keras.engine.topology import get_source_inputs

#WEIGHTS_PATH = 'D:/C/pythonEX/VGG16/vgg16_weights_tf_dim_ordering_tf_kernels.h5'
#WEIGHTS_PATH_NO_TOP = 'D:/C/pythonEX/VGG16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'

def VGG16(include_top=True, weights='imagenet',
          input_tensor=None, input_shape=None,
          pooling=None,
          classes=1000):
    # 檢查weight與分類設置是否正確
    if weights not in {'imagenet', None}:
        raise ValueError('The `weights` argument should be either '
                         '`None` (random initialization) or `imagenet` '
                         '(pre-training on ImageNet).')

    if weights == 'imagenet' and include_top and classes != 1000:
        raise ValueError('If using `weights` as imagenet with `include_top`'
                         ' as true, `classes` should be 1000')

    # 設置圖像尺寸,相似caffe中的transform
    # Determine proper input shape
    input_shape = _obtain_input_shape(input_shape,
                                      default_size=224,
                                      min_size=48,
                                      # 模型所能接受的最小長寬
                                      data_format=K.image_data_format(),
                                      # 數據的使用格式
                                      require_flatten=include_top)
                                      #是否經過一個Flatten層再鏈接到分類器

    # 數據簡單處理,resize
    if input_tensor is None:
        img_input = Input(shape=input_shape)
        # 這裏的Input是keras的格式,能夠用於轉換
    else:
        if not K.is_keras_tensor(input_tensor):
            img_input = Input(tensor=input_tensor, shape=input_shape)
        else:
            img_input = input_tensor
        # 若是是tensor的數據格式,須要兩步走:
        # 先判斷是不是keras指定的數據類型,is_keras_tensor
        # 而後get_source_inputs(input_tensor)

    # 編寫網絡結構,prototxt
    # Block 1
    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)
    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)

    # Block 2
    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)
    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)

    # Block 3
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x)
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x)
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)

    # Block 4
    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x)
    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x)
    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)

    # Block 5
    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv1')(x)
    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2')(x)
    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x)

    if include_top:
        # Classification block
        x = Flatten(name='flatten')(x)
        x = Dense(4096, activation='relu', name='fc1')(x)
        x = Dense(4096, activation='relu', name='fc2')(x)
        x = Dense(classes, activation='softmax', name='predictions')(x)
    else:
        if pooling == 'avg':
            x = GlobalAveragePooling2D()(x)
        elif pooling == 'max':
            x = GlobalMaxPooling2D()(x)

    # 調整數據      
    # Ensure that the model takes into account
    # any potential predecessors of `input_tensor`.
    if input_tensor is not None:
        inputs = get_source_inputs(input_tensor)
        # get_source_inputs 返回計算須要的數據列表,List of input tensors.
        # 若是是tensor的數據格式,須要兩步走:
        # 先判斷是不是keras指定的數據類型,is_keras_tensor
        # 而後get_source_inputs(input_tensor)
    else:
        inputs = img_input

    # 建立模型
    # Create model.
    model = Model(inputs, x, name='vgg16')

    # 加載權重
    # load weights
    if weights == 'imagenet':
        if include_top:
            weights_path = 'D:/C/pythonEX/VGG16/vgg16_weights_tf_dim_ordering_tf_kernels.h5'
        else:
            weights_path = 'D:/C/pythonEX/VGG16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'
        
        model.load_weights(weights_path)

        if K.backend() == 'theano':
            layer_utils.convert_all_kernels_in_model(model)

        if K.image_data_format() == 'channels_first':
            if include_top:
                maxpool = model.get_layer(name='block5_pool')
                shape = maxpool.output_shape[1:]
                dense = model.get_layer(name='fc1')
                layer_utils.convert_dense_weights_data_format(dense, shape, 'channels_first')

            if K.backend() == 'tensorflow':
                warnings.warn('You are using the TensorFlow backend, yet you '
                              'are using the Theano '
                              'image data format convention '
                              '(`image_data_format="channels_first"`). '
                              'For best performance, set '
                              '`image_data_format="channels_last"` in '
                              'your Keras config '
                              'at ~/.keras/keras.json.')
    return model



model = VGG16(include_top=True, weights='imagenet')
img_path = 'D:/C/pythonEX/VGG16/1.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
print('Input image shape:', x.shape)

preds = model.predict(x)
print('Predicted:', decode_predictions(preds))