Keras 深度学习攻略两篇(2):迁移神经网络的实际使用(问题记录)

在MacOS构建Python深度学习开发环境 目录 构建环境 Step 1:搭建初始环境 安装Homebrew 安装Pyenv Step 2:构建开发环境 安装多版本Python 设置虚拟环境 Step 3:完善Python开发环境 训练测试 Step 1:下载源代码 Step 2:准备训练数据 Step 3:进行模型训练 Step 4:进行模型测试 参考资料 学习《深度学习推荐系统》这本书时,为加深理解,尝试以DIEN论文提及的测试程序为抓手,在MacOS工作笔记本上构建了完整的模型训练和测试环境。 构建环境 当前, 阅读详情

2.1 应对过拟合

应对过拟合的方法:
(1)增大可以用于训练的数据量

  • 数据增强

  • 增加数据样本(爬虫、多个数据集、迁移学习-预训练)
    (2)让模型能够储存更多地有效信息(量多,但要尽量不相关)
    两个:通过控制模型层的数量和层的大小来控制模型中参数的选择;另一种方法是使用权重正则化,如可以使得模型参数值更小的L1或L2正则化。

  • 卷积层、池化层、flatten层(后来的网络中用GlobalAveragePooling2D代替了flatten层)

    注意卷积核池化的本质就是降维,而由flatten到GlobalAveragePooling2D的变化,从参数的对比可以看出,显然这种改进大大的减少了参数的使用量,避免了过拟合现象。

  • drop out

数据增强

Keras ImageDataGenerator and Data Augmentation

from keras.preprocessing.image import ImageDataGenerator

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')

参数理解:

  • rotation_range is a value in degrees (0-180), a range within which to randomly rotate pictures
  • width_shift and height_shift are ranges (as a fraction of total width or height) within which to randomly translate pictures vertically or horizontally
  • rescale is a value by which we will multiply the data before any other processing. Our original images consist in RGB coefficients in the 0-255, but such values would be too high for our models to process (given a typical learning rate), so we target values between 0 and 1 instead by scaling with a 1/255. factor.
  • shear_range is for randomly applying shearing transformations
  • zoom_range is for randomly zooming inside pictures
  • horizontal_flip is for randomly flipping half of the images horizontally --relevant when there are no assumptions of horizontal assymetry (e.g. real-world pictures).
  • fill_mode is the strategy used for filling in newly created pixels, which can appear after a rotation or a width/height shift.

例子:

from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img

datagen = 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')

img = load_img('data/train/cats/cat.0.jpg')  # this is a PIL image
x = img_to_array(img)  # this is a Numpy array with shape (3, 150, 150)
x = x.reshape((1,) + x.shape)  # this is a Numpy array with shape (1, 3, 150, 150)

# the .flow() command below generates batches of randomly transformed images
# and saves the results to the `preview/` directory
i = 0
for batch in datagen.flow(x, batch_size=1,
                          save_to_dir='preview', save_prefix='cat', save_format='jpeg'):
    i += 1
    if i > 20:
        break  # otherwise the generator would loop indefinitely

在这里插入图片描述

2.2 评价指标:准确率合适么?

模型验证集准确率的方差很大的的原因会有两方面:一是准确率本身就是一个高方差的评价指;二是用于验证的指标太少。

交叉验证

一个好的解决方法就是才用采用交叉验证的方法,比如 k-fold cross-validation,但这也意味着每轮评估需要训练 k 个模型。

# MLP for Pima Indians Dataset with 10-fold cross validation
from keras.models import Sequential
from keras.layers import Dense
from sklearn.model_selection import StratifiedKFold
import numpy
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# load pima indians dataset
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]
# define 10-fold cross validation test harness
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
cvscores = []
for train, test in kfold.split(X, Y):
  # create model
	model = Sequential()
	model.add(Dense(12, input_dim=8, activation='relu'))
	model.add(Dense(8, activation='relu'))
	model.add(Dense(1, activation='sigmoid'))
	# Compile model
	model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
	# Fit the model
	model.fit(X[train], Y[train], epochs=150, batch_size=10, verbose=0)
	# evaluate the model
	scores = model.evaluate(X[test], Y[test], verbose=0)
	print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
	cvscores.append(scores[1] * 100)
print("%.2f%% (+/- %.2f%%)" % (numpy.mean(cvscores), numpy.std(cvscores)))

一个坑:StratifiedKFold (与 Kfold 不同),它只接受 整数编码
所以,划分时,必须先抓换为整数编码,之后再变回去!

附上:转为独热编码的方法 也可点击

from numpy import array
from numpy import argmax
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
# define example
data = ['cold', 'cold', 'warm', 'cold', 'hot', 'hot', 'warm', 'cold', 'warm', 'hot']
values = array(data)
print(values)
# integer encode
label_encoder = LabelEncoder()
integer_encoded = label_encoder.fit_transform(values)
print(integer_encoded)
# binary encode
onehot_encoder = OneHotEncoder(sparse=False)
integer_encoded = integer_encoded.reshape(len(integer_encoded), 1)
onehot_encoded = onehot_encoder.fit_transform(integer_encoded)
print(onehot_encoded)
# invert first example
inverted = label_encoder.inverse_transform([argmax(onehot_encoded[0, :])])
print(inverted)

Keras 里划分数据集的方法和使用 sklearn 交叉验证集的方法:Keras验证集切分

sk-learn 官方:sklearn之交叉验证
在这里插入图片描述在这里插入图片描述疑问:
random state 设置一个固定值还是?
多维数组的话是按照第一个维度(sample)来进行划分么?

sklearn-交叉验证&GridSearch

交叉验证和Early stopping如何同时使用?

注意:因为交叉验证没有单独划分验证集,所以没办法用 val_loss 进行监控——monitor 切换为 acc

深度学习-Early stopping的作用及代码

迁移学习

另一个更加优化的方式是使用在大型数据集上进行预训练了的网络模型。这些模型已经学习到了计算机视觉问题中的绝大数特征,如果直接使用这些特征会让我们获得一个更高的准确率,相比仅使用手头的数据集的话。

(1)微调的两种思路:
(不讨论直接迁移过来,不进行训练直接预测的情况)

  1. 使用预训练模型的顶层特征( bottleneck features)——全连接层之前的最后一层的特征图,去训练我们自己的全连接层。

Our strategy will be as follow: we will only instantiate the convolutional part of the model, everything up to the fully-connected layers. We will then run this model on our training and validation data once, recording the output (the “bottleneck features” from th VGG16 model: the last activation maps before the fully-connected layers) in two numpy arrays. Then we will train a small fully-connected model on top of the stored features.
The reason why we are storing the features offline rather than adding our fully-connected model directly on top of a frozen convolutional base and running the whole thing, is computational effiency. Running VGG16 is expensive, especially if you’re working on CPU, and we want to only do it once. Note that this prevents us from using data augmentation.

  1. 微调(Fine-tuning)预训练模型的最后几层( top layers )之后,再利用这些特征去训练我们自己的全连接网络。

注意点:

  • in order to perform fine-tuning, all layers should start with properly trained weights: for instance you should not slap a randomly initialized fully-connected network on top of a pre-trained convolutional base. This is because the large gradient updates triggered by the randomly initialized weights would wreck the learned weights in the convolutional base. In our case this is why we first train the top-level classifier, and only then start fine-tuning convolutional weights alongside it.
  • we choose to only fine-tune the last convolutional block rather than the entire network in order to prevent overfitting, since the entire network would have a very large entropic capacity and thus a strong tendency to overfit. The features learned by low-level convolutional blocks are more general, less abstract than those found higher-up, so it is sensible to keep the first few blocks fixed (more general features) and only fine-tune the last one (more specialized features).
  • fine-tuning should be done with a very slow learning rate, and typically with the SGD optimizer rather than an adaptative learning rate optimizer such as RMSProp. This is to make sure that the magnitude of the updates stays very small, so as not to wreck the previously learned features.

具体以 VGG16 网络为例,使用Keras进行迁移学习:

  • 冻结除了全连接层以外的全部的网络,最一层的特征图作为我们训练自己全连接网络的特征。
    在这里插入图片描述

  • 训练全连接之前的最后几层网络,然后将特数据用于自己新定义的网络上进行训练

    在这里插入图片描述

  • 实际代码:以 Fine-tune InceptionV3 为例

    from keras.applications.inception_v3 import InceptionV3
    from keras.preprocessing import image
    from keras.models import Model
    from keras.layers import Dense, GlobalAveragePooling2D
    from keras import backend as K
    
    # create the base pre-trained model
    base_model = InceptionV3(weights='imagenet', include_top=False)
    
    # add a global spatial average pooling layer
    x = base_model.output
    x = GlobalAveragePooling2D()(x)
    # let's add a fully-connected layer
    x = Dense(1024, activation='relu')(x)
    # and a logistic layer -- let's say we have 200 classes
    predictions = Dense(200, activation='softmax')(x)
    
    # this is the model we will train
    model = Model(inputs=base_model.input, outputs=predictions)
    
    # first: train only the top layers (which were randomly initialized)
    # i.e. freeze all convolutional InceptionV3 layers
    for layer in base_model.layers:
        layer.trainable = False
    
    # compile the model (should be done *after* setting layers to non-trainable)
    model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
    
    # train the model on the new data for a few epochs
    model.fit_generator(...)
    
    # at this point, the top layers are well trained and we can start fine-tuning
    # convolutional layers from inception V3. We will freeze the bottom N layers
    # and train the remaining top layers.
    
    # let's visualize layer names and layer indices to see how many layers
    # we should freeze:
    for i, layer in enumerate(base_model.layers):
       print(i, layer.name)
    
    # we chose to train the top 2 inception blocks, i.e. we will freeze
    # the first 249 layers and unfreeze the rest:
    for layer in model.layers[:249]:
       layer.trainable = False
    for layer in model.layers[249:]:
       layer.trainable = True
    
    # we need to recompile the model for these modifications to take effect
    # we use SGD with a low learning rate
    from keras.optimizers import SGD
    model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='categorical_crossentropy')
    
    # we train our model again (this time fine-tuning the top 2 inception blocks
    # alongside the top Dense layers
    model.fit_generator(...)
    

等多的关于使用迁移神经网络作为输入特征,或者选取具体某一层的特征图作为特征的方法,可以继续参考 Keras Documentation。

以VGG16为例的迁移学习模板:

# -*- coding: UTF-8 -*-
import keras
from keras import Model
from keras.applications import VGG16
from keras.callbacks import TensorBoard, ModelCheckpoint
from keras.layers import Flatten, Dense, Dropout, GlobalAveragePooling2D
from keras.models import load_model
from keras.preprocessing import image
from PIL import ImageFile
import numpy as np
import tensorflow as tf
from keras.preprocessing.image import ImageDataGenerator
from datetime import datetime
TIMESTAMP = "{0:%Y-%m-%dT%H-%M-%S/}".format(datetime.now())
ImageFile.LOAD_TRUNCATED_IMAGES = True
 
 
EPOCHS = 30
BATCH_SIZE = 16
DATA_TRAIN_PATH = 'D:/data/train'
 
 
 
def Train():
    #-------------准备数据--------------------------
    #数据集目录应该是 train/LabelA/1.jpg  train/LabelB/1.jpg这样
    gen = ImageDataGenerator(rescale=1. / 255)  
    train_generator = gen.flow_from_directory(DATA_TRAIN_PATH, (224,224)), shuffle=False,
                                              batch_size=BATCH_SIZE, class_mode='categorical')
 
    #-------------加载VGG模型并且添加自己的层----------------------
    #这里自己添加的层需要不断调整超参数来提升结果,输出类别更改softmax层即可
 
    #参数说明:inlucde_top:是否包含最上方的Dense层,input_shape:输入的图像大小(width,height,channel)                                         
    base_model = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
    x = base_model.output
    x=Flatten()(x)
    x = Dense(256, activation='relu')(x)
    x = Dropout(0.5)(x)
    x = Dense(1, activation='sigmoid')(x)
    predictions = Dense(2, activation='softmax')(x)
    model = Model(input=base_model.input, output=predictions)
 
 
    #-----------控制需要FineTune的层数,不FineTune的就直接冻结
    for layer in base_model.layers:
        layer.trainable = False
 
    #----------编译,设置优化器,损失函数,性能指标
    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy', metrics=['accuracy'])
 
    #----------设置tensorboard,用来观察acc和loss的曲线---------------
    tbCallBack = TensorBoard(log_dir='./logs/' + TIMESTAMP,  # log 目录
                             histogram_freq=0,  # 按照何等频率(epoch)来计算直方图,0为不计算
                             batch_size=16,  # 用多大量的数据计算直方图
                             write_graph=True,  # 是否存储网络结构图
                             write_grads=True,  # 是否可视化梯度直方图
                             write_images=True,  # 是否可视化参数
                             embeddings_freq=0,
                             embeddings_layer_names=None,
                             embeddings_metadata=None)
 
    #---------设置自动保存点,acc最好的时候就会自动保存一次,会覆盖之前的存档---------------
    checkpoint = ModelCheckpoint(filepath='HatNewModel.h5', monitor='acc', mode='auto', save_best_only='True')
 
    #----------开始训练---------------------------------------------
    model.fit_generator(generator=train_generator,
                        epochs=EPOCHS,
                        callbacks=[tbCallBack,checkpoint],
                        verbose=2
                        )
 
 
#-------------预测单个图像--------------------------------------
def Predict(imgPath):
    model = load_model(SAVE_MODEL_NAME)
    img = image.load_img(imgPath, target_size=(224, 224))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    res = model.predict(x)
    print(np.argmax(res, axis=1)[0])
以上运行环境:

Keras2.1.4

Tensorflow-gpu 1.5

CUDA9.0

cudnn7.0

python3.5

更多微调的例例子:

VGG16
VGG19
VGG16 Fine-tuning model
How to make Fine tuning model by Keras

Keras 迁移学习的例子:
Keras预训练模型综合对比

(2)选择那一层的特征作为训练特征的问题
(结合自己之前在CK+上的实验!直接作为结论)

微调前,先查看预训练到的模型:层数和名称:

# check the layers by name
for i,layer in enumerate(vgg_model.layers):
    print(i,layer.name)

2.3 如何提高迁移学习的效果

  • 保证测试新的数据集时,也进行跟训练集一样的预处理过程

Edit: To ensure that image is processed in same way as the training
images are processed use keras generator only

            samplewise_std_normalization=True)

test_generator = test_datagen.flow_from_directory(
        args.validate_dir,  # this is the target directory
        target_size=(512, 512),  
        batch_size=batch_size,
        class_mode='categorical', shuffle=True)

Now test_generator.next() will return X,Y pair which can be used for
prediction checks.

I have ignored rotations and all from ImageDataGenerator as they are
not changing the image properties like featurewise_center is changing.

模型/特征融合

考虑加融合机器学习分类器学到的特征

Keras Pipeline(custom generator + imgaug)

def create_model(self):
		input_layer = Input(self.input_dim)
        
		nas_mobile_model = NASNetMobile(include_top=False, input_tensor=input_layer, weights='imagenet')
		x = nas_mobile_model(input_layer)

		# output layers
		x1 = GlobalAveragePooling2D()(x)
		x2 = GlobalMaxPooling2D()(x)
		x3 = Flatten()(x)

		out = Concatenate(axis=-1)([x1, x2, x3])
		out = Dropout(0.5)(out)
		output_layer = Dense(self.n_classes, activation='sigmoid')(out)

		model = Model(inputs=input_layer, outputs=output_layer)

		model.compile(optimizer=Adam(lr=0.0005), loss="binary_crossentropy", metrics=['acc'])
		return model

2.4 输入数据的格式(大小、通道数)

使用深度CNN提取建议区域的特征时,需要注意的是,有些网络对输入图片的大小有要求,如Alex-net要求输入的图片尺寸为227像素*227像素的大小。

全卷网络的输入可以是任意大小,含有全连接层则需固定大小。
(卷积层对于图像是没有尺寸限制要求)——需要好好研究

模型数据格式(大小、通道数)的限制问题:默认要求输入彩色图和一定大小 (224x224)
(1)例如通道数的问题:
(三通道) 预训练数据应用到(单通道)灰度图,可能出现的问题:

  • 数据格式不对——只能强制性转换数据:
    ① 一维到三维(repeat 一维灰度图到3维)
faces = np.repeat(faces, 3, -1)

② 三维到一维(只提出一维卷积数据 or 将特征图flaten到一维)

img_input = Input(shape=(img_size_target,img_size_target,1))
img_conc = Concatenate()([img_input, img_input, img_input])    

model = Unet(backbone_name='resnet34', input_tensor=img_conc, encoder_weights='imagenet', freeze_encoder=True)

详见

(2)又或者迁移神经网络对输入数据有最小尺寸的要求,比如VGG16,最小为48x48——用opencv转换是否合算?
DeepLearning(keras框架)–图像输入大小及通道调整问题
——直接改变迁移网络的输入input?(因为)

# load model without classifier layers
model = VGG16(include_top=False, input_shape=(48, 48, 3))

值得注意的是,如果输入大小不是224也不要紧,只要在全连接层之前使用全局平均池化就行。(但是需要满足预训练网络的最小尺寸大小,比如VGG16最小尺寸是48x48 查看)

If your model uses a global average pooling before the “dense” classification layer, then it does not matter how large the inputs are. You can input a 600x480 image and the model will give a prediction for the full image.

However, if you wanted to take 224x224 crops from the 600x480 image, you could first resize it so the smallest side is 256. That would make the input image 320x256. Now you can take 224x224 crops from this resized image.

模型小型化(降维)

(类似从VGG到Inception的操作)

Commonly used CNNs for feature extraction include a set of fully connected layers at the end. Fully connected layers tend to contain most of the parameters in a CNN. Specifically, VGG16 [10] contains approximately 90% of all its parameters in their last fully connected layers. Recent architectures such as Inception V3 [12], reduced the amount of parameters in their last layers by including a Global Average Pooling operation. Global Average Pooling reduces each feature map into a scalar value by taking the average over all elements in the feature map. The average operation forces the network to extract global features from the input image. Modern CNN architectures such as Xception [1] leverage from the combination of two of the most successful experimental assumptions in CNNs: the use of residual modules [6] and depth-wise separable convolutions [2]. Depth-wise separable convolutions reduce further the amount of parameters by separating the processes of feature extraction and combination within a convolutional layer.

如何手动打乱多维数据

打乱 多维的 X
  • 打乱第一个轴:np.random.shuffle(arr)

    This function only shuffles the array along the first axis of a multi-dimensional array. The order of sub-arrays is changed but
    their contents remains the same.

    Parameter
    ---------- x : array_like
    The array or list to be shuffled.

    Returns
    ------- None

  • 打乱指定的轴 :apply_along_axis

import numpy as np
a = np.arange(40).reshape((5,8))       
# shuffle along axis 1     
np.apply_along_axis(np.random.shuffle,1,a) 
shuffle along axis 0
np.random.shuffle(a)
print(a)
打乱多维的 X 和 y

只需对下面代码进行些许修改,将 len(data) 换为第一维 大小

# 随机打乱 序列
index = [i for i in range(len(data))] 
random.shuffle(index)
data = data[index]
label = label[index]

结果如下:


# 随机打乱多维数组 X 和 y (三维数据)
import random
X = np.arange(0, 12).reshape(2, 3, 2)

Y = np.arange(0, 10, 6).reshape(-1, 1)
print(X)
print(Y)
index = [i for i in range(X.shape[0])] 
# print(index)
random.shuffle(index)

X = X[index]
Y = Y[index]  

# print(X.shape, Y.shape)
print(X) 
print(Y)
[[[ 0  1]
  [ 2  3]
  [ 4  5]]

 [[ 6  7]
  [ 8  9]
  [10 11]]]
[[0]
 [6]]
[[[ 6  7]
  [ 8  9]
  [10 11]]

 [[ 0  1]
  [ 2  3]
  [ 4  5]]]
[[6]
 [0]]
# 随机打乱多维数组 X 和 y  (四维数据)
import random
X = np.arange(0, 16).reshape(2, 2, 2, 2)

Y = np.arange(0, 2).reshape(-1, 1)
print(X)
print(Y)
index = [i for i in range(X.shape[0])] 
# print(index)
random.shuffle(index)

X = X[index]
Y = Y[index]  

print(X.shape, Y.shape)
print(X) 
print(Y)
[[[[ 0  1]
   [ 2  3]]

  [[ 4  5]
   [ 6  7]]]


 [[[ 8  9]
   [10 11]]

  [[12 13]
   [14 15]]]]
[[0]
 [1]]
(2, 2, 2, 2) (2, 1)
[[[[ 8  9]
   [10 11]]

  [[12 13]
   [14 15]]]


 [[[ 0  1]
   [ 2  3]]

  [[ 4  5]
   [ 6  7]]]]
[[1]
 [0]]

2.4 模型训练

如何划分:训练集、验证集和测试集

比较全面的经验:深度学习Keras采坑经验

2.5 分析与可视化

混淆矩阵

  • 需要注意的是:
    y_test 需要由 one-hot 编码格式变为 个位数字代表的编码。
    不然会出现如下报错:
    confusion matrix error “Classification metrics can’t handle a mix of multilabel-indicator and multiclass targets”

  • 解决:

import numpy as np
rounded_labels=np.argmax(test_labels, axis=1)
rounded_labels[1]

1 .python实现混淆矩阵
在这里插入图片描述
2. 数据可视化-混淆矩阵(confusion matrix)

在这里插入图片描述

  • 最简例子1:
# 混淆矩阵

import seaborn as sns
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt

sns.set()
f,ax=plt.subplots()
y_true = [0,0,1,2,1,2,0,2,2,0,1,1]
y_pred = [1,0,1,2,1,0,0,2,2,0,1,1]
C2= confusion_matrix(y_true, y_pred, labels=[0, 1, 2])
print(C2) #打印出来看看
sns.heatmap(C2,annot=True,ax=ax) #画热力图

ax.set_title('Confusion matrix') #标题
ax.set_xlabel('Predict') #x轴
ax.set_ylabel('True') #y轴
  • 例子2:
import keras
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

from sklearn.metrics import confusion_matrix

# === dataset ===
with np.load('mnist.npz') as f:
    x_train, y_train = f['x_train'], f['y_train']
    x_test, y_test = f['x_test'], f['y_test']

x_train = x_train.reshape(60000, 28, 28, 1)
x_test = x_test.reshape(10000, 28, 28, 1)
print(x_train.shape)
print(x_test.shape)

# === model: CNN ===
model = keras.models.Sequential()
model.add(keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(keras.layers.MaxPooling2D((2, 2)))
model.add(keras.layers.Conv2D(64, (3, 3), activation='relu'))
model.add(keras.layers.MaxPooling2D((2, 2)))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(64, activation='relu'))
model.add(keras.layers.Dense(10, activation='softmax'))
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
model.summary()

# === train ===
model.fit(x=x_train, y=y_train,
          batch_size=512,
          epochs=10,
          validation_data=(x_test, y_test))

# === pred ===
y_pred = model.predict_classes(x_test)
print(y_pred)

# === 混淆矩阵:真实值与预测值的对比 ===
# https://scikit-learn.org/stable/auto_examples/model_selection/plot_confusion_matrix.html
con_mat = confusion_matrix(y_test, y_pred)

con_mat_norm = con_mat.astype('float') / con_mat.sum(axis=1)[:, np.newaxis]     # 归一化
con_mat_norm = np.around(con_mat_norm, decimals=2)

# === plot ===
plt.figure(figsize=(8, 8))
sns.heatmap(con_mat_norm, annot=True, cmap='Blues')

plt.ylim(0, 10)
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()

如何调整学习率、如何实现“早停”

比较全面的经验:深度学习Keras采坑经验

模型的可视化

这部分:更详细

Keras Documentation-Model visualization

from keras.applications.vgg16 import VGG16
from keras.utils.vis_utils import plot_model
model = VGG16()
plot_model(model, to_file='vgg.png')

训练过程可视化

(1)方法一:
在这里插入图片描述

import matplotlib.pyplot as plt

history = model.fit(x, y, validation_split=0.25, epochs=50, batch_size=16, verbose=1)

# Plot training & validation accuracy values
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()

# Plot training & validation loss values
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()

(2)方法二
在这里插入图片描述

import keras

#写一个LossHistory类,保存loss和acc
class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = {'batch': [], 'epoch': []}
        self.accuracy = {'batch': [], 'epoch': []}
        self.val_loss = {'batch': [], 'epoch': []}
        self.val_acc = {'batch': [], 'epoch': []}

    def on_batch_end(self, batch, logs={}):
        self.losses['batch'].append(logs.get('loss'))
        self.accuracy['batch'].append(logs.get('acc'))
        self.val_loss['batch'].append(logs.get('val_loss'))
        self.val_acc['batch'].append(logs.get('val_acc'))

    def on_epoch_end(self, batch, logs={}):
        self.losses['epoch'].append(logs.get('loss'))
        self.accuracy['epoch'].append(logs.get('acc'))
        self.val_loss['epoch'].append(logs.get('val_loss'))
        self.val_acc['epoch'].append(logs.get('val_acc'))

    def loss_plot(self, loss_type):
        iters = range(len(self.losses[loss_type]))
        #创建一个图
        plt.figure()
        # acc
        plt.plot(iters, self.accuracy[loss_type], 'r', label='train acc')#plt.plot(x,y),这个将数据画成曲线
        # loss
        plt.plot(iters, self.losses[loss_type], 'g', label='train loss')
        if loss_type == 'epoch':
            # val_acc
            plt.plot(iters, self.val_acc[loss_type], 'b', label='val acc')
            # val_loss
            plt.plot(iters, self.val_loss[loss_type], 'k', label='val loss')
        plt.grid(True)#设置网格形式
        plt.xlabel(loss_type)
        plt.ylabel('acc-loss')#给x,y轴加注释
        plt.legend(loc="upper right")#设置图例显示位置
        plt.show()
        
# 创建一个实例history
history = LossHistory()

再其放入 fit 函数 callbacks=[history]) #callbacks回调,将数据传给history

另一个例子

特征图/模型可视化

CNN 卷积核/层输出可视化

模型保存

Callback 回调是Keras的一个类,是在训练过程的特定阶段调用的一组函数,可以使用回调来获取训练期间内部状态和模型统计信息的视图。

Callback 方法:

  • History
    History对象即为fit方法的返回值

  • ModelCheckpoint
    该回调函数将在每个epoch后保存模型到filepath

  • TensorBoard
    该回调函数是一个可视化的展示器

  • CSVLogger
    将epoch的训练结果保存在csv文件中,支持所有可被转换为string的值,包括1D的可迭代数值如np.ndarray.

  • LambdaCallback
    用于创建简单的callback的callback类

训练过程为什么震荡?——试着增大 batch size

训练过程曲线分析:acc/loss/val_acc/val_loss

如设置神经网络参数

bath_size

学习率

卷积核的的大小、卷积步长和卷积核的个数

「卷积核」漫游指南

深层CNN的调参经验

  • 卷积核的的大小
    卷积核大小(Kernel Size)
    定义了卷积操作的感受野(Receptive Field)。在二维卷积中,通常设置为 3 ,即卷积核大小为 3×3。
    卷积核大小,一般都是 奇数x奇数 。直观的理解是,奇数形态的卷积核有中心点,对边沿、对线条更加敏感,可以更有效的提取边沿信息。如果是偶数的话,效率会相对较差,积累起来整体效率就会非常差。
    卷积核的大小越大,其感受野(Receptive Field)越大,看到的信息越多,提取的特征就会越优秀。
    但是尺寸越大,其计算量就越大,对于有限算力而言,因其训练时间过长,不利于训练模型,也不利于加深网络。

  • 步长
    步幅(Stride)
    定义了卷积核遍历图像时的步幅大小。其默认值通常设置为 1 ,也可将步幅设置为 2 后对图像进行下采样,这种方式与最大池化类似。

…
小结:

一个卷积核的尺寸越大,其感受野越大,所能提取的特征就越优异,但是其参数量也会几何倍数地增长,在现有算力的情况下,不利于网络训练及加深。

为了更快的训练网络并加深网络,我们要找一种「减少参数量,但不影响精度」的解决办法。于是产生了:

  • 利用多个小卷积核替代一个大的卷积核(减少参数量)
  • 先使用 1x1 卷积核将输入数据降维的 Bottleneck 技术(减少参数量)
  • 相当于 5x5 卷积核的 3x3 空洞卷积核 [扩张率为 1 ](减少参数量)
  • 单一尺寸卷积核用多尺寸卷积核代替(多尺度观察)
  • 参数量不变(3x3),但是提取有效信息更多的 可变形卷积核

综合经验

实践(从零开始不断的trial-and-error)

Using convolutional neural nets to detect facial keypoints tutorial

参考:

博客

  1. Keras Documentation
  2. Illustrated: 10 CNN Architectures
  3. keras系列︱迁移学习:利用InceptionV3进行fine-tuning及预测、完美案例(五)
  4. 深度学习在表情识别中的应用
  5. Building powerful image classification models using very little data
  6. DeepLearning(keras框架)–图像输入大小及通道调整问题
  7. Display Deep Learning Model Training History in Keras

论文

  1. Gradient-Based Learning Applied to Document Recognition
  2. ImageNet Classification with Deep Convolutional Neural Networks
  3. Very Deep Convolutional Networks for Large-Scale Image Recognition
  4. Going Deeper with Convolutions
图像算法学习全攻略:从OpenCV基础到深度学习实战 图像算法是计算机视觉的核心,它通过数学和编程模型处理数字图像信息。其基本原理涉及将图像视为像素矩阵,运用线性代数、微积分和概率统计进行分析与变换。在技术价值上,图像算法能实现从基础的图像增强、特征提取到复杂的目标识别与场景理解,是人工智能感知世界的关键。应用场景广泛覆盖自动驾驶、医疗影像、工业质检和消费电子等领域。本文聚焦于构建系统的图像算法知识体系,特别强调从经典算法(如OpenCV中的滤波、边缘检测、SIFT特征提取)入手,再过渡到深度学习(如CNN、YOLO),并深入探讨了二维图形骨架分割等专题,为初 阅读详情

相关推荐

PyTorch与TensorFlow双框架实战:环境配置、训练与部署全攻略

深度学习框架是构建神经网络模型的基石,PyTorch和TensorFlow是当前两大主流选择。它们分别基于动态计算图和静态图机制,前者调试灵活,后者部署优化深入,理解这些原理有助于开发者根据场景灵活选型。通过Conda虚拟环境隔离,可在一台机器上同时配置双框架,从根本上避免依赖冲突。掌握数据管道构建、GPU训练加速、模型导出(如ONNX)等通用技能,能显著提升从研究到生产的转换效率。无论是学术实验、论文复现,还是工业级服务上线,同时具备两种框架的实操能力,已成为算法工程师的核心竞争力。本文从环境搭建到分类任

weixin_34221332的博客 417

41 from keras import backend_config ImportError: cannot import name ‘get_config‘

你的代码出现了一个导入错误,提示你不能从tensorflow.python.eager.context模块中导入get_config函数。这个错误可能是因为你的tensorflow版本和keras版本不兼容。如果已经安装了tensorflow。

kewei chen 589

MNIST数据集下载与预处理全攻略:从入门到工程实践

在机器学习与深度学习领域,数据集是模型训练的基石。理解数据集的获取、加载与预处理流程,是构建有效模型的首要步骤。其核心原理在于将原始数据转化为模型可高效学习的规范化格式,这一过程直接影响模型的收敛速度与最终性能。对于计算机视觉任务,经典数据集如MNIST(手写数字识别)因其规模适中、问题定义清晰,成为验证模型基础能力与实验迭代的理想起点。通过框架内置函数(如TensorFlow/Keras的`load_data()`或PyTorch的`torchvision.datasets.MNIST`)可快速获取数据,

weixin_30596165的博客 398

keras.models导入Sequential错误

刚开始pip的最新版本的keras,找不到keras.models、 keras.layers from keras.models import Sequential from keras.layers import Dense from keras.layers import LSTM 我的tensorflow是2.0的,tensorflow.Keras中也没有Sequential, 后来发现安装低版本的可以导入, pip install Keras==2.0.2 ...

李玺 2万+

AutoML如何重塑AI工程师岗位:从调参到架构的范式迁移

AutoML并非替代算法工程师的黑箱工具,而是将机器学习工程中标准化程度高、路径明确、结果可验证的环节(如数据清洗、基线建模、模型部署)自动化封装的技术范式。其核心原理是将十年工业界沉淀的最佳实践规则库转化为可配置、可审计、可干预的软件能力,从而显著压缩建模周期、降低人力依赖、提升交付确定性。技术价值体现在工程效率跃升与能力边界重划——工程师不再消耗精力于重复劳动,而是转向更高阶任务:定义业务约束、设计人机协同协议、构建领域知识图谱。典型应用场景覆盖金融风控、医疗影像辅助诊断、工业质检、政务政策匹配等需快速

weixin_34007020的博客 417

3分钟搞定TensorFlow环境:Conda虚拟环境安装与验证全攻略

在机器学习与AI应用开发中,环境配置是许多开发者面临的首要挑战。虚拟环境技术通过为每个项目创建独立的Python运行环境,从根本上解决了不同项目间依赖包版本冲突的问题。其核心原理是利用环境隔离机制,确保项目所需的特定库版本互不干扰。这一实践对于TensorFlow这类依赖复杂的科学计算框架尤为重要,因为其底层涉及大量C/C++库和硬件加速组件。通过使用Conda这一跨平台的环境管理器,开发者不仅能管理Python包,还能一站式处理CUDA、cuDNN等系统级依赖,实现环境的快速搭建与复现。在模型训练、算法研

weixin_33850890的博客 312

Tensorflow中使用Keras自定义数据集 分布式训练 极简教程

Tensorflow中使用Keras自定义数据集 分布式训练 极简教程前言分布式训练自定义数据集分布式模型配置分布式数据集配置坑与须知 前言   连滚带爬的摸索了一周,网上的教程参差不齐,都是在讲一大堆概念,而没有动手的教程。就算是动手的教程,也大都版本太旧,而且是在理想状态下的试验,不符合每个人的需求。最后经过摸索,终于跑通了!其实说白了,就是希望能有一个教程,从自己的数据集,自己的模型开始教分布式训练。   本篇教程基于Tensorflow 2.1 !很多分布式的东西在2.3才支持!!但是目前为止,还没

发布工作学习过程中遇到的问题和解决方案 1134

unity | 动画模块之滚动选项框

动画模块之滚动选项框

菌菌兹的博客 2074

【深度学习】常见的神经网络层(下)

深度学习中常见的神经网络层(下)

knighthood2001 7991

01|无代码开发 | 如何使用Zion实现导航网站制作

以上就是我制作导航网站的心得,分享给大家,作为一个小白想要独立搭建一个网站还是比较困难的,而在Zion不仅可以用可视化的方法进行搭建,甚至还可以一键发布,不用考虑服务器域名啥的问题,真是太方便了。

2301_76262110的博客 1390

Keil AC6编译器独立安装与配置指南:不升级Keil MDK也能用上新工具链

本文详细介绍了如何在不升级Keil MDK的情况下独立安装和配置Arm Compiler 6(AC6),帮助嵌入式开发者充分利用AC6的编译速度、代码密度和现代语言支持优势。通过零侵入式解决方案,开发者可以在现有环境中灵活切换编译器版本,提升开发效率。

weixin_30872157的博客 552

Msnhnet模型转换全攻略:Pytorch/Keras模型一键迁移实战

Msnhnet是一个受Darknet启发的轻量级PyTorch推理框架,支持yolov3、yolov4、yolov5、unet等多种深度学习模型。本文将详细介绍如何将Pytorch和Keras模型快速迁移到Msnhnet框架,实现模型的高效推理部署。 ## 为什么选择Msnhnet进行模型迁移? Msnhnet作为一款轻量级推理框架,具有以下显著优势: - **高效性能**:针对不同硬件平台优

gitblog_00640的博客 788

保姆级教程:用达芬奇Configurator配置CAN总线(从DBC导入到Controller设置)

本文详细介绍了使用达芬奇Configurator工具从DBC文件导入到CAN总线控制器设置的全流程配置方法。通过环境准备、CAN控制器模式选择、硬件参数配置、通信参数优化及通信栈集成等关键步骤,帮助开发者高效完成AUTOSAR架构下的CAN总线开发,特别适合汽车电子领域的工程师参考。

weixin_30529023的博客 441

DL之VGG16:基于VGG16(Keras)利用Knifey-Spoony数据集对网络架构进行迁移学习

DL之VGG16:基于VGG16(Keras)利用Knifey-Spoony数据集对网络架构迁移学习 目录 数据集 输出结果 设计思路 1、基模型 2、思路导图 核心代码 更多输出 数据集 Dataset之Knifey-Spoony:Knifey-Spoony数据集的简介、下载、使用方法之详细攻略 输出结果 ...

头部AI社区如有邀博主AI主题演讲请私信—心比天高,仗剑走天涯,保持热爱,奔赴向梦想!低调,专注,谦虚,自律,反思,成长,还算比较正能量的博主,公益免费传播…内心特别想在AI界做出一些可以推进历史进程影响力的技术(兴趣使然,有点小情怀,也有点使命感呀 5869

Openai gym environment for multi-agent games

用于多智能体游戏的 OpenAI Gym 环境

suiusoar 1193

AutoSAR MemMap模块概述及配置参数详解

这个模块是干啥的?它是用来配置Memory Mapping and Compiler Abstraction module。

4508

TensorFlow2.0与Keras实战深度学习的图像分类模型构建全攻略

使用`model.compile()`方法配置模型的学习过程。对于多分类问题,损失函数通常选择`sparse_categorical_crossentropy`或`categorical_crossentropy`。优化器是驱动模型学习的引擎,Adam优化器因其自适应学习率的特性,成为大多数情况下的默认优选。此外,还需要指定评估指标,如`accuracy`,以便在训练过程中监控模型性能。构建图像分类模型是一个系统工程,涉及数据处理、模型设计、训练优化和部署上线等多个环节。

831

【机器学习】随机森林(Random Forest,简称 RF):预测光伏电站功率 || 缺失数据处理 || 重复行处理...

【机器学习】随机森林(Random Forest,简称 RF):预测光伏电站功率。

追光者♂:记录、分享、总结、提升,现象级专栏《Python从入门到人工智能》作者,无惧黑暗,坚信曙光 1647

如何用预训练模型快速击败90%的初学者?Keras迁移学习进阶攻略

掌握TensorFlow 2.x Keras模型迁移学习,快速提升模型性能。适用于图像分类、小数据集训练等场景,通过微调预训练模型显著缩短开发周期。方法简单高效,兼顾精度与速度,助你轻松超越多数初学者,值得收藏。

InstrWander的博客 610

手把手教你学Simulink——基础储能管理场景实例:基于Simulink的压缩空气储能(CAES)系统简化模型仿真

本文介绍了基于Simulink的压缩空气储能(CAES)系统简化模型仿真方法。CAES作为大规模长时储能方案,相比锂电池具有成本低、寿命长等优势。文章详细讲解了AA-CAES系统组成、热力学建模理论,以及Simulink实现流程,包括储气室、压缩机、膨胀机等核心模块的建模方法。通过8小时充电(50MW)和6小时放电(40MW)的仿真,验证了系统可实现60%往返效率。该模型为理解CAES系统运行机制提供了实用工具,并指出热管理、储气室特性等工程实践要点,为新型电力系统储能规划提供了仿真基础。

MHD0815的博客 171

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

keras的图像预处理全攻略(一)——基本的图像变换(Image Transform)方法

keras中主要提供了主要的四个模块: (1)......\Lib\site-packages\keras\preprocessing\image.py (这个不完全,完全的详细的参考下面的序号2) (2)......\Lib\site-packages\keras_preprocessing\image.py (3)......\Lib\site-packages\keras...

MIss-Y的博客 1万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

5分钟快速上手:Style2Paints V4.5 AI绘画工具从安装到创作全攻略

想要将手绘草图一键变成精美彩色插画吗?Style2Paints V4.5正是你寻找的AI绘画神器!这款基于深度学习的智能绘画工具,能够将简单的线稿自动转化为专业级的彩色图像,无论你是绘画新手还是专业设计师,都能轻松实现从草图到成品的华丽蜕变。 ## 🎨 Style2Paints V4.5:AI绘画的革命性工具 Style2Paints V4.5是一款功能强大的AI绘画软件,它采用先进的神经网

gitblog_01115的博客 715

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

TensorFlow-Unreal实战:深度学习模型在虚幻引擎中的集成与部署

深度学习模型部署是将训练好的AI模型应用于实际生产环境的关键环节,其核心原理在于将模型的计算图与参数封装成可独立运行的推理引擎。这项技术的价值在于打通了AI训练与工程应用之间的壁垒,使得智能决策能力能够无缝嵌入到各类软件系统中。在游戏开发、实时仿真和交互式应用等场景中,模型部署能直接驱动角色行为、处理传感器数据并生成动态内容,极大地丰富了用户体验。本文聚焦于TensorFlow SavedModel格式与虚幻引擎的集成,通过MNIST手写识别、实时音频分类及自定义图像分类三个实战案例,详细阐述了从环境配置、

weixin_33735077的博客 412

Google Colab TPU实战:TensorFlow模型加速训练全攻略

张量处理单元是专为神经网络计算设计的硬件加速器,其核心原理是通过定制化电路优化矩阵运算,相比通用GPU在特定计算模式上能实现显著的性能提升。这一技术价值在于为大规模深度学习模型训练提供了高效的算力解决方案,尤其适用于处理大批次数据和Transformer等复杂架构。在工程实践中,开发者常借助云端平台如Google Colab来低成本体验TPU加速,通过适配TensorFlow计算图与构建高效数据管道,可大幅缩短模型训练时间。本文将深入解析在Colab环境中配置TPU策略、优化数据输入流程以及调试常见问题的完

weixin_30855099的博客 383

ImageNet数据集下载与处理全攻略:从官方渠道到高效数据管道搭建

在计算机视觉和深度学习领域,大规模图像数据集是模型训练与评估的基石。ImageNet作为该领域的基准数据集,其重要性源于其按WordNet层次结构组织的超大规模图像集合,直接推动了AlexNet、ResNet等里程碑模型的诞生。理解数据集的获取、处理与加载原理,对于模型复现、迁移学习和算法验证具有关键的技术价值。在实际工程实践中,无论是通过官方渠道、学术镜像还是框架内置接口获取数据,都需关注数据的完整性与预处理一致性。本文将围绕ImageNet数据集的下载策略、目录结构组织、以及高效数据加载管道的搭建,深入

weixin_34290631的博客 293

诸神缄默不语-个人技术博文与视频目录

诸神缄默不语的优快云博文目录

诸神缄默不语的博客 1万+
上一篇: Keras 深度学习攻略两篇(1):十种卷积神经网络(CNN)框架——总结与可视化分析
下一篇: 理解深度学习基础——神经网络的起源和发展
Robin_Pi
博客等级 码龄9年 2万+粉丝 632原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值