Keras Basic Usage

阅读: 评论:0

Keras Basic Usage

Keras Basic Usage

Keras Basic Usage

Keras是一个基于Python的深度学习库,是一个高级的神经网络API,可以运行在Tensorflow, CNTK, Theano等深度学习框架的顶层。对于研究者来说,使用Keras可以快速开发和构建深度学习模型。

tf.keras是Google根据Keras API进行的Tensorflow版本的实现。官网上给出了一个非常简短的例子来介绍Keras的使用方法,我们来看一下:

首先check一下tensorflow和keras的版本

Python 3.6.8 |Anaconda, Inc.| (default, Dec 29 2018, 19:04:46)
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf
>>> tf.__version__
'1.12.0'
>>> tf.keras.__version__
'2.1.6-tf'

接下来我们运行一下TF官网上给出的Demo

from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
# Load mnist dataset
mnist = tf.ist 
# 获取训练集和测试集
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 数据预处理,此处利用到了归一化
x_train, x_test = x_train / 255.0, x_test / 255.0
# 搭建神经网络
model = dels.Sequential([tf.keras.layers.Flatten(input_shape=(28, 28)),tf.keras.layers.Dense(128, activation='relu'),tf.keras.layers.Dropout(0.2),tf.keras.layers.Dense(10, activation='softmax')
])
# 选择优化器,损失函数和模型度量方法
modelpile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
# 模型拟合
model.fit(x_train, y_train, epochs=5)
# 模型评价
model.evaluate(x_test, y_test)

如果读者之前没有运行过这段代码,那么首先这段代码会下载mnist,之后便是模型训练的结果。

Downloading data from .npz
11493376/11490434 [==============================] - 152s 13us/step
Epoch 1/5
2019-07-13 21:38:59.927952: I tensorflow/core/platform/cpu_feature_guard:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
60000/60000 [==============================] - 5s 77us/step - loss: 0.3011 - acc: 0.9134
Epoch 2/5
60000/60000 [==============================] - 4s 60us/step - loss: 0.1430 - acc: 0.9581
Epoch 3/5
60000/60000 [==============================] - 4s 61us/step - loss: 0.1068 - acc: 0.9673
Epoch 4/5
60000/60000 [==============================] - 4s 61us/step - loss: 0.0868 - acc: 0.9739
Epoch 5/5
60000/60000 [==============================] - 4s 63us/step - loss: 0.0749 - acc: 0.976910000/10000 [==============================] - 0s 29us/step
[0.07364166865674779, 0.9761]

可以看到,模型在训练了5个epoch之后,就达到了0.9769的精度,在验证集上的精度也达到了0.9761的精度。我们搭建了一个简易的带有Dropout功能的全连接网络,就能在mnist数据集上达到不俗的精度。而且,上面这段代码并不难理解。

显然地,对于演示Demo来讲,这段代码确实简单。但是在实际项目生产中,有很多需要注意的点,本文将从以下几个部分来说明Keras的使用方法与需要注意的点。主要是:1. 版本问题;2. 数据加载;3. 模型构建;4. 损失函数,优化器,度量方法选择;5. 模型拟合。

版本问题

TF是公认的向下兼容性比较差,这也就意味着高版本的代码大多数情况下无法在低版本的TF框架下运行,或多或少地都需要改变一些代码的细节,这个问题一直被TF的使用者所诟病。所以,在使用TF前,读者应该要仔细Check框架版本,以免到时候出现一些莫名其妙的问题。

如果需要使用GPU,除了CheckTF的版本之外,还需要注意计算机上所安装的CUDA版本与cuDNN的版本。以下是tf-gpu的版本所对应的CUDA和cuDNN版本。更多细节可查看

查看TF和Keras版本的方法我们在上面已经给出了,下面给出查看本机CUDA和cuDNN版本的方法。如果没有安装CUDA,则下面的命令是无效的。

# 一般来说,CUDA会安装在/usr/local文件夹下面
$ cat /usr/local/
# CUDA Version 9.0.176
# CUDA Patch Version 9.0.176.1
# CUDA Patch Version 9.0.176.2
# CUDA Patch Version 9.0.176.3
# CUDA Patch Version 9.0.176.4
# 查看cuDNN版本
$ cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2
# #define CUDNN_MAJOR 7
# #define CUDNN_MINOR 5
# #define CUDNN_PATCHLEVEL 0
# --
# define CUDNN_VERSION (CUDNN_MAJOR * 1000 + CUDNN_MINOR * 100 + CUDNN_PATCHLEVEL)# #include "driver_types.h"

确保TF-GPU支持CUDA和cuDNN版本之后,我们就可以进行模型编写与训练工作。当然,如果读者不需要使用GPU,那么只需CheckTF的版本即可。

数据加载

在TF官网上给出的Demo里面,我们看到数据加载就只有一行mnist.load_data(),实际上这只是对mnist数据集进行的一个封装。在实际应用中,数据来源可能是多种多样的,这里以Figaro1k发型分类数据为例,说明数据构建和加载的基本流程。在后续,笔者会给出适用于更多形式和更多场景的数据构建和加载方式。

对图片分类问题而言,Keras的数据加载方式比原生TF简单太多。读者只需要两步操作就可以加载图片。
Step 1. 构建图片数据的生成器

from functools import partial
from keras_preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(preprocessing_function=partial(resnet50.preprocess_input, data_format='channels_last'),rotation_range=20,width_shift_range=0.2,height_shift_range=0.2,horizontal_flip=True,vertical_flip=True,featurewise_center=False,samplewise_center=False,featurewise_std_normalization=False,samplewise_std_normalization=False,zca_whitening=False,zca_epsilon=1e-6,brightness_range=None,shear_range=0.,zoom_range=0.,channel_shift_range=0.,fill_mode='nearest',cval=0.,rescale=None,data_format='channels_last',validation_split=0.0,interpolation_order=1,dtype='float32')

我们看到,该段代码建立了一个ImageDataGenerator对象,这个对象有非常多的参数,大部分的参数是图片在训练前的一些预处理工作,比如图片增强,归一化等等,其中preprocessing_function参数是用户指定的图片预处理方法。

Step 2. 指定数据读取方式

train_generator = train_datagen.flow_from_directory(directory=train_data_path,target_size=(224, 224),color_mode='rgb',classes=None,class_mode='categorical',batch_size=batch_size,shuffle=True,seed=None,save_to_dir=None,save_prefix='',save_format='jpg',follow_links=False,subset=None,interpolation='nearest')

上述代码指定数据从哪里获取,flow_from_directory指定数据是从文件夹中获取的,其中directory参数指定文件夹的路径,需要注意的是,在图片分类问题中,这个函数会自动的搜索train_data_path下的子文件夹,并认为不同的子文件夹下的图片属于不同的类。

上图表示了图片文件的存储结构,读者在使用这个函数进行图片分类的时候,只需要将图片按照上述方式组织即可。通过上述两行代码,我们就构建好了训练数据的生成器。验证数据的构建过程和上述过程类似,但需要注意的是,验证过程是不需要对图片进行增强的。

所以验证数据一般通过如下手段进行加载。


val_datagen = ImageDataGenerator(preprocessing_function=partial(resnet50.preprocess_input, data_format='channels_last'), featurewise_center=False,samplewise_center=False,featurewise_std_normalization=False,samplewise_std_normalization=False,zca_whitening=False,zca_epsilon=1e-6,rotation_range=0,width_shift_range=0.,height_shift_range=0.,brightness_range=None,shear_range=0.,zoom_range=0.,channel_shift_range=0.,fill_mode='nearest',cval=0.,horizontal_flip=False,vertical_flip=False,rescale=None,validation_split=0.0,interpolation_order=1,dtype='float32')val_generator = val_datagen.flow_from_directory(directory=val_data_path,target_size=(224, 224),color_mode='rgb',classes=None,class_mode='categorical',batch_size=batch_size,shuffle=True,seed=None,save_to_dir=None,save_prefix='',save_format='jpg',follow_links=False,subset=None,interpolation='nearest')

可以看到,验证阶段是不需要对图片进行增强操作的,但仍需注意的是,验证集的图片同样需要进行预处理,以保证和训练集相同的输入形式,比如归一化等操作。验证所用的图片存储结构和训练所用的图片存储结构是一样的。

读者可根据自己的需要,来调整对输入图片的一些额外的操作。

模型构建

我们以Keras预训练的ResNet50为例,Keras的模型构建同样比原生TF要简单许多。如下所示:

# 加载ResNet50预训练模型,注意,我们移除掉了ResNet50的顶层。include_top=False
model = tf.keras.applications.ResNet50(include_top=False,weights='imagenet',input_tensor=None,input_shape=(224, 224, 3),pooling=None)# 设置ResNet前面若干层不可被训练
for layer in model.layers[:-5]:ainable = False# Add output layer
new_model = models.Sequential()new_model.add(model)
# 添加顶层以适应我们的分类问题
new_model.add(layers.Conv2D(filters=1024,kernel_size=(7, 7),strides=(1, 1),padding='valid',data_format=None,dilation_rate=(1, 1),activation=None,use_bias=True,kernel_initializer='glorot_uniform',bias_initializer='zeros',kernel_regularizer=None,bias_regularizer=None,activity_regularizer=None,kernel_constraint=None,bias_constraint=None))new_model.add(layers.Flatten())new_model.add(layers.Dense(units=1024,activation=None,use_bias=True,kernel_initializer='glorot_uniform',bias_initializer='zeros',kernel_regularizer=None,bias_regularizer=None,activity_regularizer=None,kernel_constraint=None,bias_constraint=None))new_model.add(layers.lu))new_model.add(layers.Dropout(rate=0.5,noise_shape=None,seed=None))new_model.add(layers.Dense(units=7,activation=None,use_bias=True,kernel_initializer='glorot_uniform',bias_initializer='zeros',kernel_regularizer=None,bias_regularizer=None,activity_regularizer=None,kernel_constraint=None,bias_constraint=None))new_model.add(layers.softmax))

我们看到,首先加载了ResNet50预训练模型,并去除顶层,然后在根据需要添加我们自己的层。由于Figaro1k有7个类别,所以最后模型的输出层有7个输出单元,并进行了softmax操作。

损失函数,优化器,评价方法选择

这一步整合在了模型编译步骤里面,只需下面一行代码。

new_modelpile(loss='categorical_crossentropy',optimizer=optimizers.Adam(lr=1e-4),metrics=['acc'])

其中,loss指定损失函数,optimizer指定优化器,metrics指定模型评价方法。

模型拟合与验证

这一步也只需要一行代码,如下所示:

history = new_model.fit_generator(generator=train_generator,steps_per_epoch&#il(n_train_samples / batch_size),epochs=num_epochs,verbose=1,callbacks=[tensorboard_callback, lr_callback],validation_data=val_generator,validation_steps&#il(n_test_samples / batch_size),class_weight=None,max_queue_size=10,workers=1,use_multiprocessing=False,shuffle=True,initial_epoch=0)

fit_generator方法将启动模型的训练过程与验证过程,其中generator=train_generator将训练集生成器喂给模型,validation_data=val_generator指定验证集生成器,callbacks=[tensorboard_callback, lr_callback]指定回调函数,这里我们指定了两个回调,一个是tensorboard,一个是学习率衰减的回调。学习率衰减的回调函数如下:

def lr_schedule(epoch, learning_rate):"""Returns a custom learning rate that decreases as epochs progress."""# learning_rate = 1e-4if epoch > 5:learning_rate = learning_rate * 0.5if epoch > 10:learning_rate = learning_rate * 0.5if epoch > 15:learning_rate = learning_rate * 0.5if epoch > 20:learning_rate = learning_rate * 0.5if epoch > 25:learning_rate = learning_rate * 0.5if epoch > 30:learning_rate = learning_rate * 0.5if epoch > 35:learning_rate = learning_rate * 0.5if epoch > 40:learning_rate = learning_rate * 0.5# tf.summary.scalar('learning rate', learning_rate)return learning_ratelr_callback = keras.callbacks.LearningRateScheduler(schedule=lr_schedule)

应用学习率衰减的回调后,模型在训练过程会按照用户所定义的学习率衰减的schedule进行。

Tensorboard的回调方法如下:

tensorboard_callback = keras.callbacks.TensorBoard(log_dir=logdir,histogram_freq=0,batch_size=32,write_graph=True,write_grads=False,write_images=False,embeddings_freq=0,embeddings_layer_names=None,embeddings_metadata=None,embeddings_data=None)

非常遗憾的是,fit_generator目前对tensorboard的回调仅支持标量,但不支持histogram等向量的写入,相关issues:

在代码运行之后,读者可以利用

$ tensorboard --logdir=logdir

来访问Tensorboard的输出结果。

以上是Keras的基本使用过程,后续笔者会给出更多的关于Keras的细节。

完整的代码

以下为完整的代码:


from __future__ import absolute_import
from __future__ import division
from __future__ import print_functionimport os# 指定GPU
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = '0'from datetime import datetimeimport mathimport tensorflow as tffrom tensorflow.python import keras
from tensorflow.python.keras import backend as K
from keras_preprocessing.image import ImageDataGenerator
from keras_applications import resnet50models = dels
layers = keras.layers
optimizers = keras.optimizers# set GPU memory
if 'tensorflow' == K.backend():config = tf.ConfigProto()config.gpu_options.allow_growth = Truesess = tf.Session(config=config)import config
from functools import partiallogdir = "/home/wuyanxue/PyCharmProjects/hairstyle_classification/logs/scalars/" + w().strftime("%Y%m%d-%H%M%S")tensorboard_callback = keras.callbacks.TensorBoard(log_dir=logdir,histogram_freq=0,batch_size=32,write_graph=True,write_grads=False,write_images=False,embeddings_freq=0,embeddings_layer_names=None,embeddings_metadata=None,embeddings_data=None)# Define learning rate decay
def lr_schedule(epoch, learning_rate):"""Returns a custom learning rate that decreases as epochs progress."""# learning_rate = 1e-4if epoch > 5:learning_rate = learning_rate * 0.5if epoch > 10:learning_rate = learning_rate * 0.5if epoch > 15:learning_rate = learning_rate * 0.5if epoch > 20:learning_rate = learning_rate * 0.5if epoch > 25:learning_rate = learning_rate * 0.5if epoch > 30:learning_rate = learning_rate * 0.5if epoch > 35:learning_rate = learning_rate * 0.5if epoch > 40:learning_rate = learning_rate * 0.5# tf.summary.scalar('learning rate', learning_rate)return learning_ratelr_callback = keras.callbacks.LearningRateScheduler(schedule=lr_schedule)# Paramnum_epochs = 50
batch_size = 32
n_train_samples = 840
n_test_samples = 210# Datatrain_datagen = ImageDataGenerator(preprocessing_function=partial(resnet50.preprocess_input, data_format='channels_last'),rotation_range=20,width_shift_range=0.2,height_shift_range=0.2,horizontal_flip=True,vertical_flip=True,featurewise_center=False,samplewise_center=False,featurewise_std_normalization=False,samplewise_std_normalization=False,zca_whitening=False,zca_epsilon=1e-6,brightness_range=None,shear_range=0.,zoom_range=0.,channel_shift_range=0.,fill_mode='nearest',cval=0.,rescale=None,data_format='channels_last',validation_split=0.0,interpolation_order=1,dtype='float32')train_generator = train_datagen.flow_from_directory(directory=config.figaro1k_train_path,target_size=(224, 224),color_mode='rgb',classes=None,class_mode='categorical',batch_size=batch_size,shuffle=True,seed=None,save_to_dir=None,save_prefix='',save_format='jpg',follow_links=False,subset=None,interpolation='nearest')val_datagen = ImageDataGenerator(preprocessing_function=partial(resnet50.preprocess_input, data_format='channels_last'))val_generator = val_datagen.flow_from_directory(directory=config.figaro1k_test_path,target_size=(224, 224),color_mode='rgb',classes=None,class_mode='categorical',batch_size=batch_size,shuffle=True,seed=None,save_to_dir=None,save_prefix='',save_format='jpg',follow_links=False,subset=None,interpolation='nearest')# Modelmodel = tf.keras.applications.ResNet50(include_top=False,weights='imagenet',input_tensor=None,input_shape=(224, 224, 3),pooling=None)for layer in model.layers[:-5]:ainable = False# Add output layernew_model = models.Sequential()new_model.add(model)new_model.add(layers.Conv2D(filters=1024,kernel_size=(7, 7),strides=(1, 1),padding='valid',data_format=None,dilation_rate=(1, 1),activation=None,use_bias=True,kernel_initializer='glorot_uniform',bias_initializer='zeros',kernel_regularizer=None,bias_regularizer=None,activity_regularizer=None,kernel_constraint=None,bias_constraint=None))new_model.add(layers.Flatten())new_model.add(layers.Dense(units=1024,activation=None,use_bias=True,kernel_initializer='glorot_uniform',bias_initializer='zeros',kernel_regularizer=None,bias_regularizer=None,activity_regularizer=None,kernel_constraint=None,bias_constraint=None))new_model.add(layers.lu))new_model.add(layers.Dropout(rate=0.5,noise_shape=None,seed=None))new_model.add(layers.Dense(units=7,activation=None,use_bias=True,kernel_initializer='glorot_uniform',bias_initializer='zeros',kernel_regularizer=None,bias_regularizer=None,activity_regularizer=None,kernel_constraint=None,bias_constraint=None))new_model.add(layers.softmax))# new_model.summary(line_length=None,
#                   positions=None,
#                   print_fn=None)# Compilenew_modelpile(loss='categorical_crossentropy',optimizer=optimizers.Adam(lr=1e-4),metrics=['acc'])history = new_model.fit_generator(generator=train_generator,steps_per_epoch&#il(n_train_samples / batch_size),epochs=num_epochs,verbose=1,callbacks=[tensorboard_callback, lr_callback],validation_data=val_generator,validation_steps&#il(n_test_samples / batch_size),class_weight=None,max_queue_size=10,workers=1,use_multiprocessing=False,shuffle=True,initial_epoch=0)

本文发布于:2024-02-05 04:47:01,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170724465263159.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:Keras   Basic   Usage
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23