【tf.keras】在 cifar 上训练 AlexNet,数据集过大导致 OOM
cifar-10 每张图片的大小为 32×32,而 AlexNet 要求图片的输入是 224×224(也有说 227×227 的,这是 224×224 的图片进行大小为 2 的 zero padding 的结果),所以一种做法是将 cifar-10 数据集的图片 resize 到 224×224。(当然,更好的做法是修改输入层大小,并且适当对 filter 大小进行修改,可以参考 cifar10_cnn.py,虽然 cifar10_cnn.py 中的网络不是 AlexNet。)
此时遇到的问题是,cifar-10 resize 到 224×224 时,32G 内存都将无法完全加载所有数据,在归一化那一步(即每个像素点除以 255)就将发生 OOM(out of memory)。
那么此时的做法有:
1)将 resize 作为模型的一部分,如设置一个 layer 来对一个 batch 的图像进行 resize,这样 32×32 的 cifar-10 仍然可以完全加载到内存中;
2)一种通用的方法,每次只加载一部分数据到内存中,其余数据等到需要的时候再加载到内存。
注:本文 AlexNet 结构与 PyTorch 中一致。AlexNet in pytorch/vision
方法 1:加上一个 Lambda 层,对输入图片进行 resize
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.python.keras import backend as K
K.clear_session()
config = tf.ConfigProto()
config.gpu_options.allow_growth = True # 不全部占满显存, 按需分配
K.set_session(tf.Session(config=config))
# 超参数
learning_rate = 0.001
epochs = 120
batch_size = 32
cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train = x_train.astype(np.float32)
x_test = x_test.astype(np.float32)
x_train = x_train / 255
x_test = x_test / 255
model = tf.keras.models.Sequential([
# Lambda 层,对输入图片进行 resize,以下是将图片扩大了 7 倍
# resize 时,默认使用最近邻插值,想要用其它插值方式,需要直接修改 K.resize_images 方法的源代码。
layers.Lambda(lambda img: K.resize_images(img, 7, 7, data_format='channels_last'), input_shape=(32, 32, 3)),
layers.ZeroPadding2D(padding=(2, 2)),
layers.Conv2D(64, (11, 11), strides=(4, 4), padding='valid', activation='relu',
kernel_initializer='he_uniform'),
layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2)),
layers.Conv2D(192, (5, 5), strides=(1, 1), padding='same', activation='relu',
kernel_initializer='he_uniform'),
layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2)),
layers.Conv2D(384, (3, 3), strides=(1, 1), padding='same', activation='relu',
kernel_initializer='he_uniform'),
layers.Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu',
kernel_initializer='he_uniform'),
layers.Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu',
kernel_initializer='he_uniform'),
layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2)),
layers.Flatten(),
layers.Dense(4096, activation='relu', kernel_initializer='he_uniform'),
layers.Dropout(drop_rate),
layers.Dense(4096, activation='relu', kernel_initializer='he_uniform'),
layers.Dropout(drop_rate),
layers.Dense(num_classes, activation='softmax', kernel_initializer='he_uniform')
])
model.summary()
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train,
epochs=epochs,
batch_size=batch_size,
verbose=2,
validation_data=(x_val, y_val))
方法 2:使用 tensorflow.keras.utils.Sequence,构造一个 data generator
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.python.keras import backend as K
from tensorflow.keras.utils import Sequence
from sklearn.model_selection import StratifiedShuffleSplit
import cv2
import os
import numpy as np
import h5py
import time
class CIFAR10Sequence(Sequence):
def __init__(self, x_set, y_set, batch_size):
"""
:param x_set: hdf5
:param y_set: hdf5
:param batch_size: int
"""
self.x, self.y = x_set, y_set
self.batch_size = batch_size
def __len__(self):
return int(np.ceil(len(self.x) / float(self.batch_size)))
def __getitem__(self, idx):
batch_x = self.x[idx * self.batch_size:(idx + 1) * self.batch_size]
batch_y = self.y[idx * self.batch_size:(idx + 1) * self.batch_size]
batch_x = batch_x.astype(np.float32)
batch_x = batch_x / 255
return batch_x, batch_y
def _resized_data():
"""
将 resize 后的 cifar-10 保存到 'data/cifar-10.h5'
图片大小: [224, 224, 3]
:return: None
"""
cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
start_time = time.clock()
x_train = np.array([cv2.resize(img, (224, 224), interpolation=cv2.INTER_CUBIC) for img in x_train])
x_test = np.array([cv2.resize(img, (224, 224), interpolation=cv2.INTER_CUBIC) for img in x_test])
# initialize
x_val = np.array([])
y_val = np.array([])
sss = StratifiedShuffleSplit(n_splits=1, test_size=0.1, random_state=32)
for train_index, val_index in sss.split(x_train, y_train):
print("TRAIN:", train_index, "VAL:", val_index)
x_train, x_val = x_train[train_index], x_train[val_index]
y_train, y_val = y_train[train_index], y_train[val_index]
end_time = time.clock()
print('Time consuming of resizing: ', (end_time - start_time))
# 写文件
filename = 'data/cifar-10.h5'
h5f = h5py.File(filename, 'w')
h5f.create_dataset('x_train', data=x_train)
h5f.create_dataset('y_train', data=y_train)
h5f.create_dataset('x_val', data=x_val)
h5f.create_dataset('y_val', data=y_val)
h5f.create_dataset('x_test', data=x_test)
h5f.create_dataset('y_test', data=y_test)
h5f.close()
def load_resized_data(filename='data/cifar-10.h5'):
if not os.path.exists(filename):
_resized_data()
# 不要关闭 h5 文件,否则将无法读取数据,这一步并不会直接将数据加载到内存中
# h5 文件支持切片读取,而且也很快
h5f = h5py.File(filename, 'r')
x_train = h5f['x_train']
y_train = h5f['y_train']
x_val = h5f['x_val']
y_val = h5f['y_val']
x_test = h5f['x_test']
y_test = h5f['y_test']
return (x_train, y_train), (x_val, y_val), (x_test, y_test)
K.clear_session()
config = tf.ConfigProto()
config.gpu_options.allow_growth = True # 不全部占满显存, 按需分配
K.set_session(tf.Session(config=config))
# 超参数
learning_rate = 0.001
epochs = 120
batch_size = 32
(x_train, y_train), (x_val, y_val), (x_test, y_test) = load_resized_data()
x_val = x_val.astype(np.float32)
x_test = x_test.astype(np.float32)
x_val = x_val / 255
x_test = x_test / 255
model = tf.keras.models.Sequential([
layers.ZeroPadding2D(padding=(2, 2), input_shape=(224, 224, 3)),
layers.Conv2D(64, (11, 11), strides=(4, 4), padding='valid', activation='relu',
kernel_initializer='he_uniform'),
layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2)),
layers.Conv2D(192, (5, 5), strides=(1, 1), padding='same', activation='relu',
kernel_initializer='he_uniform'),
layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2)),
layers.Conv2D(384, (3, 3), strides=(1, 1), padding='same', activation='relu',
kernel_initializer='he_uniform'),
layers.Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu',
kernel_initializer='he_uniform'),
layers.Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu',
kernel_initializer='he_uniform'),
layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2)),
layers.Flatten(),
layers.Dense(4096, activation='relu', kernel_initializer='he_uniform'),
layers.Dropout(drop_rate),
layers.Dense(4096, activation='relu', kernel_initializer='he_uniform'),
layers.Dropout(drop_rate),
layers.Dense(num_classes, activation='softmax', kernel_initializer='he_uniform')
])
model.summary()
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# shuffle 默认为 True, 意味着在训练一个 epoch 之后,CIFAR10Sequence 的 idx 会随机选择,而不是顺序选择,这样在 batch-level 进行了随机,一个 batch 内的样本顺序是固定的
model.fit_generator(CIFAR10Sequence(x_train, y_train, batch_size=batch_size),
# steps_per_epoch=int(np.ceil(len(x_train)/batch_size)),
epochs=epochs,
verbose=2,
callbacks=None,
validation_data=(x_val[:], y_val[:]))
References
class CIFAR10Sequence(Sequence) -- github
keras.utils.Sequence()
AlexNet in pytorch/vision
【tf.keras】在 cifar 上训练 AlexNet,数据集过大导致 OOM的更多相关文章
- [Tensorflow] 使用 tf.keras.utils.get_file() 下载 MS-COCO 2014 数据集
import argparse import tensorflow as tf tf.enable_eager_execution() def main(args): ""&quo ...
- Keras学习:试用卷积-训练CIFAR-10数据集
import numpy as np import cPickle import keras as ks from keras.layers import Dense, Activation, Fla ...
- 【tf.keras】使用手册
目录 0. 简介 1. 安装 1.1 安装 CUDA 和 cuDNN 2. 数据集 2.1 使用 tensorflow_datasets 导入公共数据集 2.2 数据集过大导致内存溢出 2.3 加载 ...
- 使用Keras进行多GPU训练 multi_gpu_model
使用Keras训练具有多个GPU的深度神经网络(照片来源:Nor-Tech.com). 摘要 在今天的博客文章中,我们学习了如何使用多个GPU来训练基于Keras的深度神经网络. 使用多个GPU使我们 ...
- 【tf.keras】tf.keras加载AlexNet预训练模型
目录 从 PyTorch 中导出模型参数 第 0 步:配置环境 第 1 步:安装 MMdnn 第 2 步:得到 PyTorch 保存完整结构和参数的模型(pth 文件) 第 3 步:导出 PyTorc ...
- 基于tensorflow2.0 使用tf.keras实现Fashion MNIST
本次使用的是2.0测试版,正式版估计会很快就上线了 tf2好像更新了蛮多东西 虽然教程不多 还是找了个试试 的确简单不少,但是还是比较喜欢现在这种写法 老样子先导入库 import tensorflo ...
- TensorFlow2.0(11):tf.keras建模三部曲
.caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px so ...
- 一文上手Tensorflow2.0之tf.keras(三)
系列文章目录: Tensorflow2.0 介绍 Tensorflow 常见基本概念 从1.x 到2.0 的变化 Tensorflow2.0 的架构 Tensorflow2.0 的安装(CPU和GPU ...
- 1.keras实现-->使用预训练的卷积神经网络(VGG16)
VGG16内置于Keras,可以通过keras.applications模块中导入. --------------------------------------------------------将 ...
随机推荐
- 在 win10 环境下,设置自己写的 程序 开机自动 启动的方法
原文:在 win10 环境下,设置自己写的 程序 开机自动 启动的方法 1.是登录自己用户时才能开机启 C:\Users\username\AppData\Roaming\Microsoft\Wind ...
- 将RDL报表转换成RDLC报表的函数
原文:将RDL报表转换成RDLC报表的函数 近日研究RDLC报表,发现其不能与RDL报表兼容,尤其是将RDL报表转换成RDLC报表.网上的资料贴出的的转换方式复杂且不切实际,遂决定深入研究.经研究发现 ...
- c# SQLHelper总汇
/// <summary> /// The SqlHelper class is intended to encapsulate high performance, /// scalabl ...
- windows下的getopt/getoptlong函数(拷贝GNU C的库函数)
http://www.cnblogs.com/oloroso/p/4856104.html
- 通过Chrome扩展来批量复制知乎好友
1.初始化文件 Chrome 官方扩展教程地址 新建一个文件夹 zhi-follow 下图中 1 部分为 默认的图标3种尺寸 会显示在 Chrome 中 2. 定义按钮样式 页面上会有 ...
- python脚本,重新设置图片大小
最近在做一个android的电台,此android程序要访问自己服务器上的歌曲文件,包括图片.这些文件要自己手动上传. 每天十首歌,需要二十个图片(一个大图450*450.一个小图140*140). ...
- WPF使用AForge实现Webcam预览(二)
本文主要介绍如何让摄像头预览界面的宽高比始终在16:9. 首先我们需要修改一下上一篇随笔实现的UI界面,让Grid变成一个3*3的九宫格,预览界面位于正中间.Xaml示例代码如下: <Windo ...
- 转换GMT秒数为日期时间格式-Delphi源码
转换GMT秒数为日期时间格式-Delphi源码.收藏最近在写PE分析工具的时候,需要转换TimeDateStamp字段值为日期时间格式,这是Delphi的源码. //把GMT时间的秒数转换成日期时间格 ...
- MQTT-CN MQTT协议中文版
欢迎任何形式的转载,但请务必注明出处:http://www.cnblogs.com/liangjingyang 项目地址:https://github.com/liangjingyang/MQTT-C ...
- 《Windows via C/C++》学习笔记 —— 设备I/O之“同步的设备I/O”(系列文章)
前面曾经讲过,设备I/O的方式有两种:同步和异步.本篇介绍一下同步设备I/O.主要涉及到两个函数:ReadFile和WriteFile. 不要被这两个函数的名称迷惑,不仅可以将这两个作用于文件,也可以 ...