我不是来自cs背景,我正在尝试创建一个分类器,在其中我提供包含疾病和图像而没有疾病的图像。我试图使用初始v3进行微调。不幸的是,所有用于微调的示例都是针对vgg-16完成的,并且他们停止说初始v3几乎在所有教程中都经过类似的训练。我正在使用带有tensorflow后端的keras。每个人都告诉我要截断最终的softmax图层并添加两个图层并进行微调。我不知道如何在初始阶段添加图层我还要将我的数据存储在2个文件夹中这也让我头疼因为一些教程加载了cifar数据库,而其他人使用目录,我也对此感到不舒服。任何人都可以提供一些意见吗?
train.py
import os
import sys
import glob
import argparse
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt
from keras import backend as K
from keras import __version__
from keras.applications.inception_v3 import InceptionV3, preprocess_input
from keras.models import Model
from keras.layers import Dense, AveragePooling2D, GlobalAveragePooling2D, Input, Flatten, Dropout
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import SGD
IM_WIDTH, IM_HEIGHT = 299, 299 #fixed size for InceptionV3
NB_EPOCHS = 3
BAT_SIZE = 32
FC_SIZE = 1024
#NB_IV3_LAYERS_TO_FREEZE = 172
def get_nb_files(directory):
"""Get number of files by searching directory recursively"""
if not os.path.exists(directory):
return 0
cnt = 0
for r, dirs, files in os.walk(directory):
for dr in dirs:
cnt += len(glob.glob(os.path.join(r, dr + "/*")))
return cnt
def setup_to_transfer_learn(model, base_model):
"""Freeze all layers and compile the model"""
for layer in base_model.layers:
layer.trainable = False
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
def add_new_last_layer(base_model, nb_classes):
"""Add last layer to the convnet
Args:
base_model: keras model excluding top
nb_classes: # of classes
Returns:
new keras model with last layer
"""
x = base_model.output
x = AveragePooling2D((8, 8), border_mode='valid', name='avg_pool')(x)
x = Dropout(0.5)(x)
x = Flatten()(x)
predictions = Dense(2, activation='softmax')(x)
model = Model(input=base_model.input, output=predictions)
return model
"""
def setup_to_finetune(model):
Freeze the bottom NB_IV3_LAYERS and retrain the remaining top layers.
note: NB_IV3_LAYERS corresponds to the top 2 inception blocks in the inceptionv3 arch
Args:
model: keras model
for layer in model.layers[:NB_IV3_LAYERS_TO_FREEZE]:
layer.trainable = False
for layer in model.layers[NB_IV3_LAYERS_TO_FREEZE:]:
layer.trainable = True
model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='categorical_crossentropy', metrics=['accuracy'])
"""
def train(args):
"""Use transfer learning and fine-tuning to train a network on a new dataset"""
train_img = 'training_set/'
validation_img = 'test_set/'
nb_epoch = int(args.nb_epoch)
nb_train_samples = get_nb_files(train_img)
nb_classes = len(glob.glob(train_img + "/*"))
# data prep
train_datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
validation_datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
train_generator = train_datagen.flow_from_directory(
train_img,
target_size=(299, 299),
batch_size=32,
class_mode='categorical')
validation_generator = validation_datagen.flow_from_directory(
validation_img,
target_size=(299, 299),
batch_size=32,
class_mode='categorical')
if(K.image_dim_ordering() == 'th'):
input_tensor = Input(shape=(3, 299, 299))
else:
input_tensor = Input(shape=(299, 299, 3))
# setup model
base_model = InceptionV3(input_tensor = input_tensor,weights='imagenet', include_top=False,input_shape=(IM_HEIGHT,IM_WIDTH,3)) #include_top=False excludes final FC layer
model = add_new_last_layer(base_model, nb_classes)
# transfer learning
setup_to_transfer_learn(model, base_model)
history_tl = model.fit_generator(train_generator,
samples_per_epoch=320,
nb_epoch=nb_epoch,
validation_data=validation_generator,
nb_val_samples=64)
model.save(args.output_model_file)
if args.plot:
plot_training(history_tl)
def plot_training(history):
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(len(acc))
plt.plot(epochs, acc, 'r.')
plt.plot(epochs, val_acc, 'r')
plt.title('Training and validation accuracy')
plt.savefig('accuracy.png')
plt.figure()
plt.plot(epochs, loss, 'r.')
plt.plot(epochs, val_loss, 'r-')
plt.title('Training and validation loss')
plt.savefig('loss.png')
if __name__=="__main__":
a = argparse.ArgumentParser()
a.add_argument("--nb_epoch", default=NB_EPOCHS)
a.add_argument("--batch_size", default=BAT_SIZE)
a.add_argument("--plot", action="store_true")
a.add_argument("--output_model_file", default="inceptionv3-ft.model")
args = a.parse_args()
train(args)
predictions.py
import sys
import argparse
import numpy as np
from PIL import Image
import requests
from io import BytesIO
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt
from keras.preprocessing import image
from keras.models import load_model
from keras.applications.inception_v3 import preprocess_input
target_size = (299, 299) #fixed size for InceptionV3 architecture
def predict(model, img, target_size):
"""Run model prediction on image
Args:
model: keras model
img: PIL format image
target_size: (w,h) tuple
Returns:
list of predicted labels and their probabilities
"""
if img.size != target_size:
img = img.resize(target_size)
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
preds = model.predict(x)
return preds[0]
def plot_preds(image, preds):
"""Displays image and the top-n predicted probabilities in a bar graph
Args:
image: PIL image
preds: list of predicted labels and their probabilities
"""
plt.figure()
labels = (" NO DR", "DR")
plt.barh([0, 1], preds, alpha=0.5)
plt.yticks([0, 1], labels)
plt.xlabel('Probability')
plt.xlim(0,1.01)
plt.tight_layout()
plt.savefig('out.png')
if __name__=="__main__":
a = argparse.ArgumentParser()
a.add_argument("--image", help="path to image")
a.add_argument("--image_url", help="url to image")
a.add_argument("--model")
args = a.parse_args()
if args.image is None and args.image_url is None:
a.print_help()
sys.exit(1)
model = load_model(args.model)
if args.image is not None:
img = Image.open(args.image)
preds = predict(model, img, target_size)
plot_preds(img, preds)
if args.image_url is not None:
response = requests.get(args.image_url)
img = Image.open(BytesIO(response.content))
preds = predict(model, img, target_size)
plot_preds(img, preds)
最后,我将通过参数传递图像,并以PNG文件的形式获得结果。
答案 0 :(得分:2)
您似乎有多个不相关的问题,但几乎所有问题都已在stackoverflow中得到解答。我会尝试编译一些信息给你一些方向:
我提供包含疾病和没有疾病的图像的图像[...]每个人都告诉我截断最终的softmax层开始并添加两层并进行微调
我认为在没有“顶级”密集图层(包含softmax
)的情况下加载模型会更加清晰,并自己重新添加顶层:
# This will load inception without its top dense layers (there's only 2).
model = InceptionV3(..., weights='imagenet', include_top=False)
x = model.output
# Re-add the layers here, with new weights.
x = GlobalAveragePooling2D(name='avg_pool')(x)
x = Dense(2, activation='softmax', name='predictions')(x)
model = Model(inputs=model.inputs, outputs=x)
请注意,您不应同时使用GlobalAveragePooling2D
和Flatten
,就像在火车脚本中一样。
如果您使用VGG16
,架构会有所不同:
model = VGG16(..., weights='imagenet', include_top=False)
x = model.output
x = Flatten(name='flatten')(x)
x = Dense(4096, activation='relu', name='fc1')(x)
x = Dense(4096, activation='relu', name='fc2')(x)
x = Dense(2, activation='softmax', name='predictions')(x)
注意:您可能想要更改这些4096
。他们似乎只有两个班级有点高。
keras中的我也将我的数据存储在2个文件夹中,这也让我感到头疼,因为有些教程加载了cifar数据库,而其他人使用目录,我也对此感到不舒服。
cifar
数据库是一个玩具示例。调试开始以确保其他所有内容都顺利运行。这就是它可以直接加载到主存储器中的原因
真实的数据集需要存储到磁盘中
如果它们包含在以其标签命名的子代码中,例如:
train/
|-label_a/
|-label_b/
...
|-label_z/
valid/
|-label_a/
|-label_b/
...
|-label_z/
然后有一个帮手可以自动加载这些图像并将它们与正确的标签相关联:
from keras.preprocessing.image import ImageDataGenerator
from keras.applications.inception_v3 import preprocess_input
# or from keras.applications.vgg16 import preprocess_input
train_dir = '/datasets/problem/train/'
valid_dir = '/datasets/problem/valid/'
g = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest',
preprocessing_function=preprocess_input)
train = g.flow_from_directory(train_dir,
target_size=(256, 256),
batch_size=32,
shuffle=True)
valid = g.flow_from_directory(valid_dir,
target_size=(256, 256),
batch_size=32,
shuffle=True)
注意:您的火车脚本似乎就是这种情况。
如果您的数据集不是这样的,那么您需要实现一个能够为您加载数据并将其与相应标签相关联的Sequence
。