文章目录

  • 一、环境配置
  • 二、命令行介绍
  • 三、训练简单的神经网络
    • 1.导入包
    • 2.命令行参数设置
    • 3.数据集读取
    • 4.模型搭建
    • 5.模型编译
    • 6.模型训练
    • 7.模型预测及可视化
    • 8.模型存储
    • 9.新数据预测
  • 四、进阶操作
    • 1.简单的卷积神经网络模型(VGG)
    • 2.停止训练和恢复训练
      • 1.停止训练/保存模型
      • 2.恢复训练
      • 3.callback高级用法
    • 3.学习率相关设置
      • 1.标准学习率衰减
      • 2.使用callback回调函数进行修改学习率
      • 3.循环学习率
        • 1.三角形
        • 2.三角形2
        • 3.指数变化
      • 4.寻找最佳的学习率
    • 4.数据增强
      • 1.数据扩增
      • 2.数据替换
      • 3.行为克隆(behavioral cloning)
    • 5.迁移学习
      • 1.特征抽取
        • 原理及代码实现
        • 存在的问题及解决办法1
        • 解决办法2
      • 2.微调(fine-tuning)

最近发现了一个很好的关于计算机视觉的网站 pyimagesearch,英文的教学网站, OCR,目标检测,实例分割等都挺全的,准备扒下来整理一个博客。
注:本文内容及代码均转自 pyimagesearch

一、环境配置

网站作者建议使用ubuntu或者Mac进行深度学习的学习,当然Windows进行基础学习也可以,Linux更多的是命令行操作。

主要环境建议Tensorflow2.0以上版本,环境配置不细说,很多教程都有
Anaconda安装
Tensorflow安装

二、命令行介绍

在Linux系统中经常使用命令行进行程序的训练,预测等,训练时要经常调整超参数以保证达到更高的准确率,但每次调整参数都要重新修改py文件是件很费时的事情,这就需要argparse包进行命令行参数的设置。

# import the necessary packages
import argparse
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-n", "--name", required=True,help="name of the user")
args = vars(ap.parse_args())
# display a friendly message to the user
print("Hi there {}, it's nice to meet you!".format(args["name"]))

首先导入argparse包,接下来创建ArgumentParser对象,然后使用add_argument方法添加想要的参数,添加完将其转换为字典变量,字典的键为参数名称,字典的值为输入的值,接下来就可以使用这个字典进行后续操作了。

$ python simple_example.py --help
usage: simple_example.py [-h] -n NAME
optional arguments:-h, --help            show this help message and exit-n NAME, --name NAME  name of the user$ python simple_example.py --name YourNameHere
Hi there YourNameHere, it's nice to meet you!

在命令行中输入如上代码即可,如果有更多参数就在后面依次添加,也可以使用–help来查看帮助信息。

三、训练简单的神经网络

原文链接

1.导入包

# set the matplotlib backend so figures can be saved in the background
import matplotlib
matplotlib.use("Agg")
# import the necessary packages
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import SGD
from imutils import paths
import matplotlib.pyplot as plt
import numpy as np
import argparse
import random
import pickle
import cv2
import os

sklearn是常用的机器学习库,imutils和OpenCV差不多,matplotlib可视化工具,argparse命令行参数

2.命令行参数设置

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True,help="path to input dataset of images")
ap.add_argument("-m", "--model", required=True,help="path to output trained model")
ap.add_argument("-l", "--label-bin", required=True,help="path to output label binarizer")
ap.add_argument("-p", "--plot", required=True,help="path to output accuracy/loss plot")
args = vars(ap.parse_args())

四个参数分别是数据集路径,输出的模型路径,输出类别信息路径和存放准确率/loss图表的路径

3.数据集读取

# initialize the data and labels
print("[INFO] loading images...")
data = []
labels = []
# grab the image paths and randomly shuffle them
imagePaths = sorted(list(paths.list_images(args["dataset"])))
random.seed(42)
random.shuffle(imagePaths)
# loop over the input images
for imagePath in imagePaths:# load the image, resize the image to be 32x32 pixels (ignoring# aspect ratio), flatten the image into 32x32x3=3072 pixel image# into a list, and store the image in the data listimage = cv2.imread(imagePath)image = cv2.resize(image, (32, 32)).flatten()data.append(image)# extract the class label from the image path and update the# labels listlabel = imagePath.split(os.path.sep)[-2]labels.append(label)# scale the raw pixel intensities to the range [0, 1]
data = np.array(data, dtype="float") / 255.0
labels = np.array(labels)# partition the data into training and testing splits using 75% of
# the data for training and the remaining 25% for testing
(trainX, testX, trainY, testY) = train_test_split(data,labels, test_size=0.25, random_state=42)# convert the labels from integers to vectors (for 2-class, binary
# classification you should use Keras' to_categorical function
# instead as the scikit-learn's LabelBinarizer will not return a
# vector)
lb = LabelBinarizer()
trainY = lb.fit_transform(trainY)
testY = lb.transform(testY)

1.首先创建数据集和标签,由于图片比较小可以存在一个列表里,对于较大图片,可以用一个列表存储图片路径,标签和路径有关,这里图像转换成一维向量方便送入后面的线性层,若使用卷积神经网络则不用转换维度
2.之后将数据和标签转换为numpy array变量,
3.划分训练集合测试集,
4.将标签转换为向量格式

4.模型搭建

# define the 3072-1024-512-3 architecture using Keras
model = Sequential()
model.add(Dense(1024, input_shape=(3072,), activation="sigmoid"))
model.add(Dense(512, activation="sigmoid"))
model.add(Dense(len(lb.classes_), activation="softmax"))

这里的网络只添加了三个线性层

5.模型编译

# initialize our initial learning rate and # of epochs to train for
INIT_LR = 0.01
EPOCHS = 80
# compile the model using SGD as our optimizer and categorical
# cross-entropy loss (you'll want to use binary_crossentropy
# for 2-class classification)
print("[INFO] training network...")
opt = SGD(lr=INIT_LR)
model.compile(loss="categorical_crossentropy", optimizer=opt,metrics=["accuracy"])

优化函数选择SGD

6.模型训练

# train the neural network
H = model.fit(x=trainX, y=trainY, validation_data=(testX, testY),epochs=EPOCHS, batch_size=32)

7.模型预测及可视化

# evaluate the network
print("[INFO] evaluating network...")
predictions = model.predict(x=testX, batch_size=32)
print(classification_report(testY.argmax(axis=1),predictions.argmax(axis=1), target_names=lb.classes_))
# plot the training loss and accuracy
N = np.arange(0, EPOCHS)
plt.style.use("ggplot")
plt.figure()
plt.plot(N, H.history["loss"], label="train_loss")
plt.plot(N, H.history["val_loss"], label="val_loss")
plt.plot(N, H.history["accuracy"], label="train_acc")
plt.plot(N, H.history["val_accuracy"], label="val_acc")
plt.title("Training Loss and Accuracy (Simple NN)")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend()
plt.savefig(args["plot"])

8.模型存储

# save the model and label binarizer to disk
print("[INFO] serializing network and label binarizer...")
model.save(args["model"], save_format="h5")
f = open(args["label_bin"], "wb")
f.write(pickle.dumps(lb))
f.close()

9.新数据预测

# load the input image and resize it to the target spatial dimensions
image = cv2.imread("new image")
output = image.copy()
image = cv2.resize(image, (args["width"], args["height"]))
# scale the pixel values to [0, 1]
image = image.astype("float") / 255.0# check to see if we should flatten the image and add a batch
# dimension
if args["flatten"] > 0:image = image.flatten()image = image.reshape((1, image.shape[0]))
# otherwise, we must be working with a CNN -- don't flatten the
# image, simply add the batch dimension
else:image = image.reshape((1, image.shape[0], image.shape[1],image.shape[2]))# load the model and label binarizer
print("[INFO] loading network and label binarizer...")
model = load_model(args["model"])
lb = pickle.loads(open(args["label_bin"], "rb").read())
# make a prediction on the image
preds = model.predict(image)
# find the class label index with the largest corresponding
# probability
i = preds.argmax(axis=1)[0]
label = lb.classes_[i]

四、进阶操作

1.简单的卷积神经网络模型(VGG)

原文链接

# import the necessary packages
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import BatchNormalization
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.layers import MaxPooling2D
from tensorflow.keras.layers import Activation
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Dropout
from tensorflow.keras.layers import Dense
from tensorflow.keras import backend as Kclass SmallVGGNet:@staticmethoddef build(width, height, depth, classes):# initialize the model along with the input shape to be# "channels last" and the channels dimension itselfmodel = Sequential()inputShape = (height, width, depth)chanDim = -1# if we are using "channels first", update the input shape# and channels dimensionif K.image_data_format() == "channels_first":inputShape = (depth, height, width)chanDim = 1# CONV => RELU => POOL layer setmodel.add(Conv2D(32, (3, 3), padding="same",input_shape=inputShape))model.add(Activation("relu"))model.add(BatchNormalization(axis=chanDim))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Dropout(0.25))# (CONV => RELU) * 2 => POOL layer setmodel.add(Conv2D(64, (3, 3), padding="same"))model.add(Activation("relu"))model.add(BatchNormalization(axis=chanDim))model.add(Conv2D(64, (3, 3), padding="same"))model.add(Activation("relu"))model.add(BatchNormalization(axis=chanDim))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Dropout(0.25))Keras Tutorial: How to get started with Keras, Deep Learning, and Python# (CONV => RELU) * 3 => POOL layer setmodel.add(Conv2D(128, (3, 3), padding="same"))model.add(Activation("relu"))model.add(BatchNormalization(axis=chanDim))model.add(Conv2D(128, (3, 3), padding="same"))model.add(Activation("relu"))model.add(BatchNormalization(axis=chanDim))model.add(Conv2D(128, (3, 3), padding="same"))model.add(Activation("relu"))model.add(BatchNormalization(axis=chanDim))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Dropout(0.25))# first (and only) set of FC => RELU layersmodel.add(Flatten())model.add(Dense(512))model.add(Activation("relu"))model.add(BatchNormalization())model.add(Dropout(0.5))# softmax classifiermodel.add(Dense(classes))model.add(Activation("softmax"))# return the constructed network architecturereturn model

可以代替之前的线性层进行训练,不需要flatten

2.停止训练和恢复训练

原文链接
在训练神经网络的过程中,很可能因为断电、电脑死机等非人为因素或者其他原因需要停止训练并保留之前训练的模型方便之后重新恢复训练。

另外一个需要停止和恢复训练的原因是在停止训练后,我们可以调整学习率等参数使模型拟合的更好,当然也可以使用学习率衰减等策略来实现这一目的。

总而言之,停止训练和恢复训练在深度学习模型的训练过程中是有必要的,在keras中主要应用callback回调函数来实现此功能,主要实现方式如下:

1.停止训练/保存模型

# construct the set of callbacks
checkpoint = ModelCheckpoint(fname, monitor="val_loss", mode="min", save_best_only=True, verbose=1)
callbacks = [checkpoint]model.fit(x=aug.flow(trainX, trainY, batch_size=128),validation_data=(testX, testY),steps_per_epoch=len(trainX) // 128,epochs=80,callbacks=callbacks,verbose=1)

keras的callback回调函数是一组在训练的特定阶段被调用的函数集,你可以使用回调函数来观察训练过程中网络内部的状态和统计信息。通过传递回调函数列表到模型的.fit()中,即可在给定的训练阶段调用该函数集中的函数。详情参考keras官方文档

使用checkpoint函数可以对模型在每个训练期进行保存

2.恢复训练

# if there is no specific model checkpoint supplied, then initialize
# the network (ResNet-56) and compile the model
if args["model"] is None:print("[INFO] compiling model...")opt = SGD(lr=1e-1)model = ResNet.build(32, 32, 1, 10, (9, 9, 9),(64, 64, 128, 256), reg=0.0001)model.compile(loss="categorical_crossentropy", optimizer=opt,metrics=["accuracy"])
# otherwise, we're using a checkpoint model
else:# load the checkpoint from diskprint("[INFO] loading {}...".format(args["model"]))model = load_model(args["model"])# update the learning rateprint("[INFO] old learning rate: {}".format(K.get_value(model.optimizer.lr)))K.set_value(model.optimizer.lr, 1e-2)print("[INFO] new learning rate: {}".format(K.get_value(model.optimizer.lr)))

恢复训练则简单的多,加载保存的模型即可,这段代码中首先判断是否有模型需要加载,没有则正常训练,如果有模型则加载模型,这里还修改了训练时用的学习率

3.callback高级用法

通过自定义训练开始/结束、每轮开始/结束,每个batch开始/结束的函数来实现自己需要的功能

# -*- coding: utf-8 -*-
from keras import layers
from keras.callbacks import Callback
from keras.models import Sequential
from sklearn import datasetsclass MyCallback(Callback):"""Keras (version=2.3.1) Callback 编写模板"""def __init__(self):super().__init__()def on_train_begin(self, logs: dict):"""在整个训练开始时会调用次函数Parameters:----------logs: dict, 该参数在当前版本默认为 None, 主要是为未来的 keras 版本的新行为预留位置"""print('On train begin', logs)returndef on_train_end(self, logs: dict):"""在整个训练结束时调用次函数Parameters:----------logs: dict, 该参数在当前版本默认为 None, 主要是为未来的 keras 版本的新行为预留位置"""print('On train end', logs)returndef on_epoch_begin(self, epoch, logs: dict):"""在每个 epoch 开始的时候调用此函数Parameters:----------epoch: int, 当前为第几个 epoch, 从 1 开始logs: dict, 为空"""print('On epoch begin', epoch, logs)returndef on_epoch_end(self, epoch, logs: dict):"""在每个 epoch 结束的时候调用此函数Parameters:----------epoch: int, 当前为第几个 epoch, 从 1 开始logs: dict, 包含了当前 epoch 的一些信息,主要的 key 有:- accuracy- loss- val-accuracy(仅在 fit 中开启 validation 时才有)- val-loss(仅在 fit 中开启 validation 时才有)"""print('On epoch end', epoch, logs)passdef on_batch_begin(self, batch, logs: dict):"""在每个 batch 开始的时候调用此函数Parameters:----------batch: int, 当前为第几个 batch, 从 1 开始logs: dict, 包含了当前 batch 的一些信息,主要的 key 有:- batch: 同参数 batch- size: batch 的大小"""print('On batch begin', batch, logs)returndef on_batch_end(self, batch, logs: dict):"""在每个 batch 结束的时候调用此函数Parameters:----------batch: int, 当前为第几个 batch, 从 1 开始logs: dict, 包含了当前 batch 的一些信息,主要的 key 有:- batch: 同参数 batch- size: batch 的大小- loss- accuracy(仅当启用了 acc 监视)"""print('On batch end', batch, logs)return

3.学习率相关设置

学习率的调整对于神经网络的训练有着重要作用,随着训练轮数的增加,适当的修改学习率可以使训练结果更好,关于学习率的调整有如下几种方法:

1.标准学习率衰减

原文链接
最简单的修改学习率方法是在定义优化器时将参数decay进行设置,这样在使用优化器进行训练时就会相应的在每轮修改学习率。例如:

opt = SGD(lr=1e-1, momentum=0.9, decay=decay)

2.使用callback回调函数进行修改学习率

原文链接
在callback中有LearningRateScheduler函数来对学习率进行设置,schedule参数是 一个函数,接受轮索引数作为输入(整数,从 0 开始迭代) 然后返回一个学习速率作为输出(浮点数)。例子如下:

def step_decay(epoch):initial_lrate = 0.1drop = 0.5epochs_drop = 10.0lrate = initial_lrate * math.pow(drop,  math.floor((1+epoch)/epochs_drop))return lrate
schedule = LearningRateScheduler(step_decay)
callbacks = [schedule]

3.循环学习率

原文链接
循环学习率是指给定学习率最大值(上界)和最小值(下界),在训练过程中不断在界限之内变动,在每个batch过后都增加/降低学习率。这样做可以避免鞍点或局部极小值,另外能够减轻模型对学习率初值的敏感程度。

循环学习率论文介绍
循环学习率设置代码

循环学习率一共有三种形式:

1.三角形

固定上下界,学习率不断在上下界之间变化

2.三角形2

每完成一次迭代,上界降低,整体还是三角形

3.指数变化

上界按照指数变化

使用方法很简单,设置完参数后直接在callback中调用即可

clr = CyclicLR(mode=config.CLR_METHOD,base_lr=config.MIN_LR,max_lr=config.MAX_LR,step_size= config.STEP_SIZE * (trainX.shape[0] // config.BATCH_SIZE))callbacks=[clr]

4.寻找最佳的学习率

原文链接
在学习率衰减和循环学习率中都存在一个问题,如何选取恰当的初始值才能保证训练效果最好,这里介绍一种基于循环学习率的方法

首先,设置一个很小的下界(1e-10)和很大的上界(1e+1)

然后从下界开始训练,在每一个batch以指数形式更新学习率的值,并对loss取对数记录

之后继续训练直到学习率达到上界,这样大概需要1-5轮

最后可视化loss图像,选取loss开始下降的值为下界,loss由小变大的值为下界,详情如图

4.数据增强

原文链接
众所周知,数据增强是在深度学习训练中增加模型泛化能力的重要手段。在keras中,ImageDataGenerator是进行数据增强的函数,其中的参数均为各种数据增强方式,例如选择、宽/高改变等。另外,共有两种数据增强方法,分别是数据扩增和数据替换,其中数据替换比较常见。

 aug = ImageDataGenerator(rotation_range=20,zoom_range=0.15,width_shift_range=0.2,height_shift_range=0.2,shear_range=0.15,horizontal_flip=True,fill_mode="nearest")

1.数据扩增

数据扩增是指对少量图片进行旋转、裁剪等变换操作,返回原图片加上进行变换后的图片。这样做确实能够大量增加数据量,但是存在的问题是整个数据集都是基于少量的图片变换而成,对于未知图片的泛化能力依旧较弱,所以正确的做法应该是想方设法增加训练集的数量以达到更好的效果。

imageGen = aug.flow(image, batch_size=1, save_to_dir=args["output"],save_prefix="image", save_format="jpg")

使用flow方法并将参数save_to_dir,save_prefix,save_format设置好就可以将数据扩增后的图片放入文件夹中,之后可以参与训练

使用数据扩增后的数据进行训练,可以看到准确率几乎一直为1,loss也极小,说明训练并没有说明效果。

2.数据替换

数据替换则是最常见的数据增强方法,具体操作为对输入的每张图片进行旋转、裁剪等变换操作,之后返回进行变换操作之后的图片,数据量并没有改变

H = model.fit(x=aug.flow(trainX, trainY, batch_size=BS),validation_data=(testX, testY),steps_per_epoch=len(trainX) // BS,epochs=EPOCHS)

在代码中,同样使用flow方法,设置好训练集和batch_size参数即可对训练集进行数据增强

直接上结论:使用数据增强后会提高准确率

3.行为克隆(behavioral cloning)

行为克隆是一种数据增强方式,目前应用与自动驾驶数据集的创建。
自动驾驶数据集如果都采用真车进行创建是一个耗时耗钱的过程,所以使用玩游戏;写一个程序来玩游戏等方式来采集驾驶过程中的数据,将采集到的数据采用数据替换的方式进行数据增强就可以应用到训练了。

5.迁移学习

迁移学习是利用预训练模型对新的数据进行训练的过程。预训练模型通常指在ImageNet或COCO这种大型数据集上提前训练的参数,迁移学习的方式有两种:特征抽取和微调(fine-tuning)

1.特征抽取

原理及代码实现

原文链接
特征抽取的意思是指将预训练模型作为特征抽取器,例如将图片放入卷积神经网络中,经过若干层之后会得到一个特征向量,再将这个特征向量送入机器学习分类器中进行训练。最常见的两个用于特征抽取的分类器为SVM和逻辑回归。

参考代码(部分):

from tensorflow.keras.applications import VGG16
from sklearn.linear_model import LogisticRegressionmodel = VGG16(weights="imagenet", include_top=False)
features = model.predict(image, batch_size=batch_size)
features = features.reshape((features.shape[0], 7 * 7 * 512))model = LogisticRegression(solver="lbfgs", multi_class="auto",max_iter=150)
model.fit(trainX, trainY)

include_top参数即代表是否包含顶部的全连接层,因为直接使用了在imagenet上预训练的权重,所以直接进行predict就可以得到特征向量。

存在的问题及解决办法1

原文链接
在使用特征抽取时存在一个问题就是特征向量非常大的情况下很占用内存,上面例子使用VGG作为预训练模型得到的特征向量为7 * 7 * 512,当使用例如ResNet时会有7 * 7 * 2048维度的特征向量,如果同时加载数万个这样的特征向量,RAM不够使用,此时可以使用一个神经网络作为用于对抽取的特征向量进行分类的分类器,训练过程和正常的神经网络训练一样。

代码(部分)

from tensorflow.keras.applications import VGG16
# 抽取特征
model = VGG16(weights="imagenet", include_top=False)
features = model.predict(image, batch_size=batch_size)
features = features.reshape((features.shape[0], 7 * 7 * 512))# 将抽取的特征进行训练
model = Sequential()
model.add(Dense(256, input_shape=(7 * 7 * 2048,), activation="relu"))
model.add(Dense(16, activation="relu"))
model.add(Dense(len(config.CLASSES), activation="softmax"))opt = SGD(lr=1e-3, momentum=0.9, decay=1e-3 / 25)
model.compile(loss="binary_crossentropy", optimizer=opt,metrics=["accuracy"])
trainGen = generator(x, y)
H = model.fit(x=trainGen,steps_per_epoch=totalTrain // config.BATCH_SIZE,validation_data=valGen,validation_steps=totalVal // config.BATCH_SIZE,epochs=25)

解决办法2

原文链接
使用神经网络作为第二轮分类器固然是一种选择,但是如果坚持使用SVM,逻辑回归等机器学习方法,可以使用Creme。

Creme是一个在线机器学习库,拥有者和sklearn类似的API,更加容易进行在线学习。
代码如下(部分):

from creme.linear_model import LogisticRegression
from creme.multiclass import OneVsRestClassifier
from creme.preprocessing import StandardScaler
from creme.compose import Pipeline
from creme.metrics import Accuracy
from creme import stream
# csv文件为保存的特征向量
dataset = stream.iter_csv(args["csv"], target="class", converters=types)
# construct our pipeline
model = Pipeline([("scale", StandardScaler()),("learn", OneVsRestClassifier(classifier=LogisticRegression()))
])metric = Accuracy()
# loop over the dataset
for (i, (X, y)) in enumerate(dataset):# make predictions on the current set of features, train the# model on the features, and then update our metricpreds = model.predict_one(X)model = model.fit_one(X, y)metric = metric.update(y, preds)print("INFO] update {} - {}".format(i, metric))

2.微调(fine-tuning)

原文链接
微调的意思是指去掉网络末尾的全连接层,固定之前卷积层的参数,在后面加入新的全连接层并对其进行训练。通常训练时使用较小的学习率,这样做可以让全连接层能获得更前面网络的信息。当然,在某些情况下也可以不固定前面的网络层参数,而对整个网络进行训练。

模型部分代码如下(部分):

from tensorflow.keras.applications import VGG16
from tensorflow.keras.layers import Dropout
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Input
from tensorflow.keras.models import ModelbaseModel = VGG16(weights="imagenet", include_top=False)
# construct the head of the model that will be placed on top of the
# the base model
headModel = baseModel.output
headModel = Flatten(name="flatten")(headModel)
headModel = Dense(512, activation="relu")(headModel)
headModel = Dropout(0.5)(headModel)
headModel = Dense(len(config.CLASSES), activation="softmax")(headModel)
# place the head FC model on top of the base model (this will become
# the actual model we will train)
model = Model(inputs=baseModel.input, outputs=headModel)for layer in baseModel.layers:layer.trainable = False

首先调用预训练模型并将include_top设置为False,之后再添加新的全连接层,最后将预训练模型的trainable 属性设置为False就不会更改其中的参数了。

baseModel = VGG16(weights="imagenet", include_top=False,input_tensor=Input(shape=(128, 128, 3)))

当输入图片和原网络的输入维度不一致时,可通过设置input_tensor参数来修改输入维度,不同的预训练网络对输入维度有不同的最低要求,具体参照keras官方文档。注意当输入维度过大时,可能会影响模型的准确率。

计算机视觉(一)——深度学习相关推荐

  1. 全球30篇最热门的计算机视觉和深度学习论文

    全球30篇最热门的计算机视觉和深度学习论文 2016-06-23分类:机器学习评论(0) 大数据交流QQ群,汇聚2万大数据爱好者.加入,开启你的数据江湖!! 这是一份被国外专家引用最多的计算机视觉和深 ...

  2. 计算机视觉与深度学习 | 相机抖动的情况下的前景目标提取(消抖)

    ################################################ 博主github:https://github.com/MichaelBeechan 博主CSDN:h ...

  3. 计算机视觉与深度学习 | 动态背景下的前景目标提取

    ################################################ 博主github:https://github.com/MichaelBeechan 博主CSDN:h ...

  4. 计算机视觉与深度学习 | 不含动态背景的前景目标提取

    ################################################ 博主github:https://github.com/MichaelBeechan 博主CSDN:h ...

  5. CVer入门必备:计算机视觉的深度学习实践

    <计算机视觉的深度学习实践>  原价     ¥ 899.00 现超 300人报名 已至底价     ¥ 399.00  >>  点击文末阅读原文参团  << 参团 ...

  6. 华中科技大学计算机视觉张朋,计算机视觉与深度学习前沿研讨会圆满举办

    12月23日,"华中科技大学学术前沿青年团队探索论坛--计算机视觉与深度学习前沿研讨会"在一号楼学术报告厅圆满举办.此次活动由华中科技大学主办,电信学院与IEEE SPS Wuha ...

  7. 计算机视觉与深度学习基本环境安装

    计算机视觉与深度学习基本环境安装 1. Python的安装与使用 1.1 Python简介 1.2 Python下载与安装 1.2.1 Anaconda的下载与安装 1.2.2 Python编译器Py ...

  8. 笔记:计算机视觉与深度学习-北邮-鲁鹏-2020年录屏-第一讲

    笔记:计算机视觉与深度学习-北邮-鲁鹏-2020年录屏 写在开头(重复的) 1.课程来源:B站视频. 2.笔记目的:个人学习+增强记忆+方便回顾 3.时间:2021年4月8日 4.同类笔记链接:(钩子 ...

  9. 乔治亚大学招收计算机视觉/深度学习/机器人/自动驾驶博士生from 2023 spring

    University of Georgia(佐治亚大学)ECE系的Intelligent Vision and Sensing 实验室现有多个全奖博士生名额,以及1-2个csc资助的博士名额(学费由导 ...

  10. 使用计算机视觉和深度学习创建现代 OCR 管道

    文章目录 研究和原型设计 字深网 字检测器 组合式端到端系统 生产化 性能调优 优雅 在这篇文章中,我们将带您了解我们如何为[[移动文档扫描仪]构建最先进的光学字符识别(OCR)管道的幕后故事.我们使 ...

最新文章

  1. 科技部5个6G重点项目
  2. Quartz + spring 定时任务常见错误总结
  3. 计算机 课题学科代码,学科分类与代码表课题.doc
  4. MyEclipse非正常关闭问题
  5. RNN隐藏层的两种计算方法GRU和LSTM
  6. UnityShader9:光照基础回顾
  7. 【Python】利用MD5文件去重
  8. uchome登陆机制分析(一)
  9. DeFi冰火两重天:数千项目,鲜有人用,存量厮杀如何撼动传统金融?
  10. 代码实现数学图形之常用函数,幂,对数,指数,正弦,余弦,正切,余切,反正弦,反余弦,反正切,反余切,双曲正弦,双曲余弦,双曲正切,双曲余切,正割函数,余割函数,双曲正割,双曲正割.
  11. Angular 依赖注入框架里 useExisting 和 useClass 的使用场景
  12. python画圣诞帽_用Python给头像戴圣诞帽
  13. 关于“击败”团队目标的思考
  14. django踩坑关于django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.
  15. 集成微透镜阵列的CMOS传感器分析
  16. SD销售模式之MTS和MTO
  17. Swordphish——一个增强人员防钓鱼意识的安全工具
  18. 电机拖动第一二章习题总结
  19. 基于jsp+ssm+mysql实现简单的物流快递管理系统
  20. 论文阅读笔记 | 三维目标检测——VoxelNet算法

热门文章

  1. myeclipse----JVM运行内存溢出问题解决
  2. Android实例-利用WebBrowser实现浏览器(XE8+小米2)
  3. AjaxAtlas技术团队[公告]:请大家清理自己发布在团队页面上的post!
  4. 2019电子科大计算机基础知识,电子科技大学820真题1999-2019终极版.pdf
  5. android ichartjs 曲线图,C#中利用LightningChart绘制曲线图表
  6. php java session共享_PHP实现多服务器session共享之NFS共享
  7. 剑指offer面试题[40]-数组中只出现一次的数字
  8. FunTester框架Redis性能测试之list操作
  9. html5 怎么写动态图形设计,如何用SVG制作酷炫动态图标?(代码实例)
  10. 人名和成绩一起排序_excel中怎么让人名和他的成绩一起排序