深度学习-残差网络

Keras框架

Keras是一个模型级的库,提供了快速构建深度学习网络的模块。Keras并不处理如张量乘法、卷积等底层操作。这些操作依赖于某种特定的、优化良好的张量操作库。Keras依赖于处理张量的库就称为“后端引擎”。Keras提供了三种后端引擎Theano/Tensorflow/CNTK,并将其函数统一封装,使得用户可以以同一个接口调用不同后端引擎的函数

中文查询文档:https://keras.io/zh/
相关参考资料:https://blog.csdn.net/baidu_33718858/article/details/85596333
参考博客:https://blog.csdn.net/u013733326/article/details/80250818

Keras-笑脸识别

1.导入包

import numpy as np
import os
from keras import layers
from keras.layers import Input, Dense, Activation, ZeroPadding2D, BatchNormalization, Flatten, Conv2D
from keras.layers import AveragePooling2D, MaxPooling2D, Dropout, GlobalMaxPooling2D, GlobalAveragePooling2D
from keras.models import Model
from keras.preprocessing import image
from keras.utils import layer_utils
from keras.utils.data_utils import get_file
from keras.applications.imagenet_utils import preprocess_input
import pydotplus#注意这里有个坑 
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
from keras.utils import plot_model
import kt_utils

import keras.backend as K#keras后端
K.set_image_data_format('channels_last')#这个地方是设置最后一维度是通道
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow

2.我们加载数据集

X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = kt_utils.load_dataset()

# Normalize image vectors
X_train = X_train_orig/255.
X_test = X_test_orig/255.

# Reshape
Y_train = Y_train_orig.T
Y_test = Y_test_orig.T

print ("number of training examples = " + str(X_train.shape[0]))
print ("number of test examples = " + str(X_test.shape[0]))
print ("X_train shape: " + str(X_train.shape))
print ("Y_train shape: " + str(Y_train.shape))
print ("X_test shape: " + str(X_test.shape))
print ("Y_test shape: " + str(Y_test.shape))

3.我们看输出结果

number of training examples = 600
number of test examples = 150
X_train shape: (600, 64, 64, 3)
Y_train shape: (600, 1)
X_test shape: (150, 64, 64, 3)
Y_test shape: (150, 1)
这里可以看到我们的数据维度是(64,64,3)通道在最后

利用Keras框架搭建模型

#我们开始搭建模型
def model(input_shape):
     #定义一个占位符 维度为input_shape
     # 将输入占位符定义为具有形状input_shape的张量。
     # 把它想象成你的输入图像吧!
     #https://keras-cn.readthedocs.io/en/latest/layers/convolutional_layer/
     #中文文档
     X_input=Input(input_shape)
     X=ZeroPadding2D((3,3))(X_input)
     #对X开始卷积==》批量标准化===》RELU
     X=Conv2D(32,(7,7),strides=(1,1),name='conv0')(X)
     #批量标准化 axis为什么是3??通道上进行批量标准化?
     #对 batch 个数据内的每一个对应的特征图(feature map)求均值和方差
     #该层在每个batch上将前一层的激活值重新规范化,
     # 即使得其输出数据的均值接近0,其标准差接近1
     X=BatchNormalization(axis=3,name='bn0')(X)
     #relu激活
     X=Activation('relu')(X)
     #最大池化层
     #整数或长为2的整数tuple,代表在两个方向(竖直,水平)上的下采样因子,
     # 如取(2,2)将使图片在两个维度上均变为原长的一半。
     # 为整数意为各个维度值相同且为该数字
     X=MaxPooling2D((2,2),name="max_pool")(X)
     #降维度 矩阵转换为向量 +全连接层
     #Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。Flatten不影响batch的大小。
     X=Flatten()(X)
     #Dense就是常用的全连接层,所实现的运算是output = activation(dot(input, kernel)+bias)。其中activation是逐元素计算的激活函数,kernel是本层的权值矩阵,bias为偏置向量,只有当use_bias=True才会添加。
     #如果本层的输入数据的维度大于2,则会先被压为与kernel相匹配的大小
     #第一个参数为大于零的整数 是输出的维度
     X=Dense(1,activation='Sigmoid',name='fc')(X)
     #创建模型 Keras的函数式模型为Model,即广义的拥有输入和输出的模型,我们使用Model来初始化一个函数式模型
     model=Model(inputs=X_input,outputs=X,name='HappyModel')
     return model
'''
请注意:Keras框架使用的变量名和我们以前使用的numpy和TensorFlow变量不一样。
它不是在前向传播的每一步上创建新变量(比如X, Z1, A1, Z2, A2,…)以便于不同层之间的计算。
在Keras中,我们使用X覆盖了所有的值,
没有保存每一层结果,我们只需要最新的值,
唯一例外的就是X_input,
我们将它分离出来是因为它是输入的数据,
我们要在最后的创建模型那一步中用到
def HappyModel(input_shape):
    """
    实现一个检测笑容的模型

    参数:
        input_shape - 输入的数据的维度
    返回:
        model - 创建的Keras的模型

    """

    #你可以参考和上面的大纲
    X_input = Input(input_shape)

    #使用0填充:X_input的周围填充0
    X = ZeroPadding2D((3, 3))(X_input)

    #对X使用 CONV -> BN -> RELU 块
    X = Conv2D(32, (7, 7), strides=(1, 1), name='conv0')(X)
    X = BatchNormalization(axis=3, name='bn0')(X)
    X = Activation('relu')(X)

    #最大值池化层
    X = MaxPooling2D((2, 2), name='max_pool')(X)

    #降维,矩阵转化为向量 + 全连接层
    X = Flatten()(X)
    X = Dense(1, activation='sigmoid', name='fc')(X)

    #创建模型,讲话创建一个模型的实体,我们可以用它来训练、测试。
    model = Model(inputs=X_input, outputs=X, name='HappyModel')

    return model
'''
现在我们已经设计好了我们的模型了,要训练并测试模型我们需要这么做:

创建一个模型实体。
编译模型,可以使用这个语句:model.compile(optimizer = "...", loss = "...", metrics = ["accuracy"])。
训练模型:model.fit(x = ..., y = ..., epochs = ..., batch_size = ...)。
评估模型:model.evaluate(x = ..., y = ...)。
'''
#创建一个模型实体
happy_model = HappyModel(X_train.shape[1:])#从索引1开始 一直取值到最后 索引0是样本个数 我们这里不需要
#编译模型
happy_model.compile("adam","binary_crossentropy", metrics=['accuracy'])
'''
optimizer:优化器,为预定义优化器名或优化器对象,参考优化器

loss:损失函数,为预定义损失函数名或一个目标函数,参考损失函数

metrics:列表,包含评估模型在训练和测试时的性能的指标,典型用法是metrics=['accuracy']如果要在多输出模型中为不同的输出指定不同的指标,可像该参数传递一个字典,例如metrics={'ouput_a': 'accuracy'}

sample_weight_mode:如果你需要按时间步为样本赋权(2D权矩阵),将该值设为“temporal”。默认为“None”,代表按样本赋权(1D权)。如果模型有多个输出,可以向该参数传入指定sample_weight_mode的字典或列表。在下面fit函数的解释中有相关的参考内容。

weighted_metrics: metrics列表,在训练和测试过程中,这些metrics将由sample_weight或clss_weight计算并赋权

target_tensors: 默认情况下,Keras将为模型的目标创建一个占位符,该占位符在训练过程中将被目标数据代替。如果你想使用自己的目标张量(相应的,Keras将不会在训练时期望为这些目标张量载入外部的numpy数据),你可以通过该参数手动指定。目标张量可以是一个单独的张量(对应于单输出模型),也可以是一个张量列表,或者一个name->tensor的张量字典。

kwargs:使用TensorFlow作为后端请忽略该参数,若使用Theano/CNTK作为后端,kwargs的值将会传递给 K.function。如果使用TensorFlow为后端,这里的值会被传给tf.Session.run

当为参数传入非法值时会抛出异常

'''
#训练模型
#请注意,此操作会花费你大约6-10分钟。
'''
本函数用以训练模型,参数有:
x:输入数据。如果模型只有一个输入,那么x的类型是numpy array,如果模型有多个输入,那么x的类型应当为list,list的元素是对应于各个输入的numpy array。如果模型的每个输入都有名字,则可以传入一个字典,将输入名与其输入数据对应起来。
y:标签,numpy array。如果模型有多个输出,可以传入一个numpy array的list。如果模型的输出拥有名字,则可以传入一个字典,将输出名与其标签对应起来。
batch_size:整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步。
epochs:整数,训练终止时的epoch值,训练将在达到该epoch值时停止,当没有设置initial_epoch时,它就是训练的总轮数,否则训练的总轮数为epochs - inital_epoch
verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录
callbacks:list,其中的元素是keras.callbacks.Callback的对象。这个list中的回调函数将会在训练过程中的适当时机被调用,参考回调函数
validation_split:0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。注意,validation_split的划分在shuffle之后,因此如果你的数据本身是有序的,需要先手工打乱再指定validation_split,否则可能会出现验证集样本不均匀。
validation_data:形式为(X,y)或(X,y,sample_weights)的tuple,是指定的验证集。此参数将覆盖validation_spilt。
shuffle:布尔值,表示是否在训练过程中每个epoch前随机打乱输入样本的顺序。
class_weight:字典,将不同的类别映射为不同的权值,该参数用来在训练过程中调整损失函数(只能用于训练)。该参数在处理非平衡的训练数据(某些类的训练样本数很少)时,可以使得损失函数对样本数不足的数据更加关注。
sample_weight:权值的numpy array,用于在训练时调整损失函数(仅用于训练)。可以传递一个1D的与样本等长的向量用于对样本进行1对1的加权,或者在面对时序数据时,传递一个的形式为(samples,sequence_length)的矩阵来为每个时间步上的样本赋不同的权。这种情况下请确定在编译模型时添加了sample_weight_mode='temporal'。
initial_epoch: 从该参数指定的epoch开始训练,在继续之前的训练时有用。
steps_per_epoch: 一个epoch包含的步数(每一步是一个batch的数据送入),当使用如TensorFlow数据Tensor之类的输入张量进行训练时,默认的None代表自动分割,即数据集样本数/batch样本数。
validation_steps: 仅当steps_per_epoch被指定时有用,在验证集上的step总数。
输入数据与规定数据不匹配时会抛出错误
'''
happy_model.fit(X_train, Y_train, epochs=1, batch_size=50)
#评估模型
preds = happy_model.evaluate(X_test, Y_test, batch_size=32, verbose=1, sample_weight=None)
'''
本函数按batch计算在某些输入数据上模型的误差,其参数有:
x:输入数据,与fit一样,是numpy array或numpy array的list
y:标签,numpy array
batch_size:整数,含义同fit的同名参数
verbose:含义同fit的同名参数,但只能取0或1
sample_weight:numpy array,含义同fit的同名参数
本函数返回一个测试误差的标量值(如果模型没有其他评价指标),或一个标量的list(如果模型还有其他的评价指标)。model.metrics_names将给出list中各个值的含义。
如果没有特殊说明,以下函数的参数均保持与fit的同名参数相同的含义
如果没有特殊说明,以下函数的verbose参数(如果有)均只能取0或1

model.summary():打印出你的每一层的大小细节
plot_model() : 绘制出布局图
'''
print ("误差值 = " + str(preds[0]))
print ("准确度 = " + str(preds[1]))


os.environ["PATH"] += os.pathsep + 'F:\python\python\Scripts\graphviz-2.38\release\bin'
plot_model(happy_model, to_file='happy_model.png')
SVG(model_to_dot(happy_model).create(prog='dot', format='svg'))

一些其他的功能呢

1.model.summary():打印出你的每一层的大小细节
2.plot_model() : 绘制出布局图

测试你的图片

img_path = 'images/smile.jpeg'

img = image.load_img(img_path, target_size=(64, 64))
imshow(img)

x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

print(happy_model.predict(x))

输出模型图

在这里插入图片描述

残差网络

使用深层网络最大的好处就是它能够完成很复杂的功能,它能够从边缘(浅层)到非常复杂的特征(深层)中不同的抽象层次的特征中学习。然而,使用比较深的网络通常没有什么好处,一个特别大的麻烦就在于训练的时候会产生梯度消失,非常深的网络通常会有一个梯度信号,该信号会迅速的消退,从而使得梯度下降变得非常缓慢。更具体的说,在梯度下降的过程中,当你从最后一层回到第一层的时候,你在每个步骤上乘以权重矩阵,因此梯度值可以迅速的指数式地减少到0(在极少数的情况下会迅速增长,造成梯度爆炸)。

在残差网络中,一个“捷径(shortcut)”或者说“跳跃连接(skip connection)”允许梯度直接反向传播到更浅的层,如下图:
在这里插入图片描述
在这里插入图片描述

利用Keras搭建一个残差网络

恒等块
在这里插入图片描述
卷积块
在这里插入图片描述
开始搭建模型
在这里插入图片描述

import numpy as np
import tensorflow as tf

from keras import layers
from keras.layers import Input, Add, Dense, Activation, ZeroPadding2D, BatchNormalization, Flatten, Conv2D, AveragePooling2D, MaxPooling2D, GlobalMaxPooling2D
from keras.models import Model, load_model
from keras.preprocessing import image
from keras.utils import layer_utils
from keras.utils.data_utils import get_file
from keras.applications.imagenet_utils import preprocess_input
from keras.utils.vis_utils import model_to_dot
from keras.utils import plot_model
from keras.initializers import glorot_uniform

import pydotplus
from IPython.display import SVG
import scipy.misc
from matplotlib.pyplot import imshow
import keras.backend as K
K.set_image_data_format('channels_last')
K.set_learning_phase(1)
import resnets_utils


#我们开始搭建残差网络
def identity_block(X,f,filters,stage,block):
    '''

    :param X:输入的数据类型(m, n_H_prev, n_W_prev, n_H_prev)
    :param f:整数,指定主路径中间的CONV窗口的维度
    :param filters:整数列表,定义了主路径每层的卷积层的过滤器数量
    :param stage:整数,根据每层的位置来命名每一层,与block参数一起使用。
    :param block:字符串,据每层的位置来命名每一层,与stage参数一起使用
    :return:恒等块的输出,tensor类型,维度为(n_H, n_W, n_C)
    '''
    #定义命名规则
    conv_name_base="res"+str(stage)+block+"_branch"
    bn_name_base = "bn" + str(stage) + block + "_branch"
    # 获取过滤器
    F1, F2, F3 = filters
    # 保存输入数据,将会用于为主路径添加捷径
    X_shortcut = X
    #主路径第一部分
    #1.卷积层
    X=Conv2D(filters=F1,kernel_size=(1,1),strides=(1,1),padding="valid",name=conv_name_base+"2a",kernel_initializer=glorot_uniform(seed=0))(X)
    #Glorot正态分布初始化方法,也称作Xavier正态分布初始化,参数由0均值,标准差为sqrt(2 / (fan_in + fan_out))的正态分布产生,其中fan_in和fan_out是权重张量的扇入扇出(即输入和输出单元数目)
    ##归一化
    X = BatchNormalization(axis=3, name=bn_name_base + "2a")(X)
    ##使用ReLU激活函数
    X = Activation("relu")(X)
    # 主路径的第二部分
    ##卷积层
    X = Conv2D(filters=F2, kernel_size=(f, f), strides=(1, 1), padding="same",
               name=conv_name_base + "2b", kernel_initializer=glorot_uniform(seed=0))(X)
    ##归一化
    X = BatchNormalization(axis=3, name=bn_name_base + "2b")(X)
    ##使用ReLU激活函数
    X = Activation("relu")(X)

    # 主路径的第三部分
    ##卷积层
    X = Conv2D(filters=F3, kernel_size=(1, 1), strides=(1, 1), padding="valid",
               name=conv_name_base + "2c", kernel_initializer=glorot_uniform(seed=0))(X)
    ##归一化
    X = BatchNormalization(axis=3, name=bn_name_base + "2c")(X)
    ##没有ReLU激活函数

    # 最后一步:
    ##将捷径与输入加在一起
    X = Add()([X, X_shortcut])
    ##使用ReLU激活函数
    X = Activation("relu")(X)

    return X

tf.reset_default_graph()
with tf.Session() as test:
    np.random.seed(1)
    #定义占位符
    A_prev = tf.placeholder("float",[3,4,4,6])
    #随机初始化X
    X = np.random.randn(3,4,4,6)
    A = identity_block(A_prev,f=2,filters=[2,4,6],stage=1,block="a")
    #run全局变量
    test.run(tf.global_variables_initializer())
    #要使用学习阶段,只需将值“1”(训练模式)或“0”(测试模式)传递给feed_dict:
    #参数可以是单个图元素(single graph element),也可以是任意嵌套的列表list,元组tuple,名称元组namedtuple,字典dict或包含图元素的OrderedDict。A是一个列表加上[]
    out = test.run([A],feed_dict={A_prev:X,K.learning_phase():0})
    print("out = " + str(out[0][1][1][0]))
    test.close()

'''
我们已经实现了残差网络的恒等块,现在,残差网络的卷积块是另一种类型的残差块,它适用于输入输出的维度不一致的情况
它不同于上面的恒等块,与之区别在于,捷径中有一个CONV2D层
'''
def convolutional_block(X, f, filters, stage, block, s=2):
    """
    实现图5的卷积块

    参数:
        X - 输入的tensor类型的变量,维度为( m, n_H_prev, n_W_prev, n_C_prev)
        f - 整数,指定主路径中间的CONV窗口的维度
        filters - 整数列表,定义了主路径每层的卷积层的过滤器数量
        stage - 整数,根据每层的位置来命名每一层,与block参数一起使用。
        block - 字符串,据每层的位置来命名每一层,与stage参数一起使用。
        s - 整数,指定要使用的步幅

    返回:
        X - 卷积块的输出,tensor类型,维度为(n_H, n_W, n_C)
    """

    #定义命名规则
    conv_name_base = "res" + str(stage) + block + "_branch"
    bn_name_base   = "bn"  + str(stage) + block + "_branch"

    #获取过滤器数量
    F1, F2, F3 = filters

    #保存输入数据
    X_shortcut = X

    #主路径
    ##主路径第一部分
    X = Conv2D(filters=F1, kernel_size=(1,1), strides=(s,s), padding="valid",
               name=conv_name_base+"2a", kernel_initializer=glorot_uniform(seed=0))(X)
    X = BatchNormalization(axis=3,name=bn_name_base+"2a")(X)
    X = Activation("relu")(X)

    ##主路径第二部分
    X = Conv2D(filters=F2, kernel_size=(f,f), strides=(1,1), padding="same",
               name=conv_name_base+"2b", kernel_initializer=glorot_uniform(seed=0))(X)
    X = BatchNormalization(axis=3,name=bn_name_base+"2b")(X)
    X = Activation("relu")(X)

    ##主路径第三部分
    X = Conv2D(filters=F3, kernel_size=(1,1), strides=(1,1), padding="valid",
               name=conv_name_base+"2c", kernel_initializer=glorot_uniform(seed=0))(X)
    X = BatchNormalization(axis=3,name=bn_name_base+"2c")(X)

    #捷径
    X_shortcut = Conv2D(filters=F3, kernel_size=(1,1), strides=(s,s), padding="valid",
               name=conv_name_base+"1", kernel_initializer=glorot_uniform(seed=0))(X_shortcut)
    X_shortcut = BatchNormalization(axis=3,name=bn_name_base+"1")(X_shortcut)

    #最后一步
    X = Add()([X,X_shortcut])
    X = Activation("relu")(X)

    return X

tf.reset_default_graph()

with tf.Session() as test:
    np.random.seed(1)
    A_prev = tf.placeholder("float",[3,4,4,6])
    X = np.random.randn(3,4,4,6)

    A = convolutional_block(A_prev,f=2,filters=[2,4,6],stage=1,block="a")
    test.run(tf.global_variables_initializer())

    out = test.run([A],feed_dict={A_prev:X,K.learning_phase():0})
    print("out = " + str(out[0][1][1][0]))

    test.close()


#我们来搭建一个50层的残差网络
def ResNet50(input_shape=(64,64,3),classes=6):
    """
    实现ResNet50
    CONV2D -> BATCHNORM -> RELU -> MAXPOOL -> CONVBLOCK -> IDBLOCK*2 -> CONVBLOCK -> IDBLOCK*3
    -> CONVBLOCK -> IDBLOCK*5 -> CONVBLOCK -> IDBLOCK*2 -> AVGPOOL -> TOPLAYER

    参数:
        input_shape - 图像数据集的维度
        classes - 整数,分类数

    返回:
        model - Keras框架的模型

    """

    #定义tensor类型的输入数据
    X_input = Input(input_shape)

    #0填充
    X = ZeroPadding2D((3,3))(X_input)

    #stage1
    X = Conv2D(filters=64, kernel_size=(7,7), strides=(2,2), name="conv1",
               kernel_initializer=glorot_uniform(seed=0))(X)
    X = BatchNormalization(axis=3, name="bn_conv1")(X)
    X = Activation("relu")(X)
    X = MaxPooling2D(pool_size=(3,3), strides=(2,2))(X)

    #stage2
    X = convolutional_block(X, f=3, filters=[64,64,256], stage=2, block="a", s=1)
    X = identity_block(X, f=3, filters=[64,64,256], stage=2, block="b")
    X = identity_block(X, f=3, filters=[64,64,256], stage=2, block="c")

    #stage3
    X = convolutional_block(X, f=3, filters=[128,128,512], stage=3, block="a", s=2)
    X = identity_block(X, f=3, filters=[128,128,512], stage=3, block="b")
    X = identity_block(X, f=3, filters=[128,128,512], stage=3, block="c")
    X = identity_block(X, f=3, filters=[128,128,512], stage=3, block="d")

    #stage4
    X = convolutional_block(X, f=3, filters=[256,256,1024], stage=4, block="a", s=2)
    X = identity_block(X, f=3, filters=[256,256,1024], stage=4, block="b")
    X = identity_block(X, f=3, filters=[256,256,1024], stage=4, block="c")
    X = identity_block(X, f=3, filters=[256,256,1024], stage=4, block="d")
    X = identity_block(X, f=3, filters=[256,256,1024], stage=4, block="e")
    X = identity_block(X, f=3, filters=[256,256,1024], stage=4, block="f")

    #stage5
    X = convolutional_block(X, f=3, filters=[512,512,2048], stage=5, block="a", s=2)
    X = identity_block(X, f=3, filters=[512,512,2048], stage=5, block="b")
    X = identity_block(X, f=3, filters=[512,512,2048], stage=5, block="c")

    #均值池化层
    X = AveragePooling2D(pool_size=(2,2),padding="same")(X)

    #输出层
    X = Flatten()(X)
    X = Dense(classes, activation="softmax", name="fc"+str(classes),
              kernel_initializer=glorot_uniform(seed=0))(X)


    #创建模型
    model = Model(inputs=X_input, outputs=X, name="ResNet50")

    return model

model = ResNet50(input_shape=(64,64,3),classes=6)
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])

X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = resnets_utils.load_dataset()

# Normalize image vectors
X_train = X_train_orig / 255.
X_test = X_test_orig / 255.

# Convert training and test labels to one hot matrices
Y_train = resnets_utils.convert_to_one_hot(Y_train_orig, 6).T
Y_test = resnets_utils.convert_to_one_hot(Y_test_orig, 6).T

print("number of training examples = " + str(X_train.shape[0]))
print("number of test examples = " + str(X_test.shape[0]))
print("X_train shape: " + str(X_train.shape))
print("Y_train shape: " + str(Y_train.shape))
print("X_test shape: " + str(X_test.shape))
print("Y_test shape: " + str(Y_test.shape))
model.summary()
model.fit(X_train,Y_train,epochs=2,batch_size=32)
plot_model(model, to_file='model.png')
SVG(model_to_dot(model).create(prog='dot', format='svg'))

在这里插入图片描述

使用自己的图片测试

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt # plt 用于显示图片

%matplotlib inline

img_path = 'images/fingers_big/2.jpg'

my_image = image.load_img(img_path, target_size=(64, 64))
my_image = image.img_to_array(my_image)

my_image = np.expand_dims(my_image,axis=0)
my_image = preprocess_input(my_image)

print("my_image.shape = " + str(my_image.shape))

print("class prediction vector [p(0), p(1), p(2), p(3), p(4), p(5)] = ")
print(model.predict(my_image))

my_image = scipy.misc.imread(img_path)
plt.imshow(my_image)
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值