创建一个模型并编译它以从图像中提取嵌入

2024-05-16 04:12:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试将这段代码3.3 Omniglot Character set classification using Prototypical Network.ipynb从Tensorflow 1.1迁移到Tensorflow 2.x

我的怀疑是我不知道我到底在做什么。我遇到问题的代码是:

import numpy as np
import tensorflow as tf

def convolution_block(inputs, out_channels, name='conv'):

    conv = tf.layers.conv2d(inputs, out_channels, kernel_size=3, padding='SAME')
    conv = tf.contrib.layers.batch_norm(conv, updates_collections=None, decay=0.99, scale=True, center=True)
    conv = tf.nn.relu(conv)
    conv = tf.contrib.layers.max_pool2d(conv, 2)
    
    return conv

def get_embeddings(support_set, h_dim, z_dim, reuse=False):

    net = convolution_block(support_set, h_dim)
    net = convolution_block(net, h_dim)
    net = convolution_block(net, h_dim) 
    net = convolution_block(net, z_dim) 
    net = tf.contrib.layers.flatten(net)
        
    return net

我已经迁移到:

import tensorflow as tf
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D

def get_embedding_function(img_shape):
    inputs = Input(img_shape)
    conv1 = Conv2D(64, (3, 3), activation='relu', padding='same', name='conv1_1')(inputs)
    pool1 = MaxPooling2D(pool_size=(2, 2), data_format='channels_last', name='pool1')(conv1)

    conv2 = Conv2D(96, (3, 3), activation='relu', padding='same', name='conv2_1')(pool1)
    pool2 = MaxPooling2D(pool_size=(2, 2), data_format='channels_last', name='pool2')(conv2)

    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same', name='conv3_1')(pool2)
    pool3 = MaxPooling2D(pool_size=(2, 2), data_format='channels_last', name='pool3')(conv3)

    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same', name='conv4_1')(pool3)
    pool4 = MaxPooling2D(pool_size=(2, 2), data_format='channels_last', name='pool4')(conv4)

    model = tf.keras.models.Model(inputs=inputs, outputs=pool4)

    model.compile(tf.keras.optimizers.Adam(lr=(1e-4) * 2), loss='binary_crossentropy', metrics=['accuracy'])

    return model

此函数的层与前一个函数的层不同,因为我想测试自己的网络

我将使用此函数从图像中提取特征

我不得不添加model = tf.keras.models.Model(inputs=inputs, outputs=pool4),因为如果我只返回pool4,它就不起作用了。我还添加了model.compile(tf.keras.optimizers.Adam(lr=(1e-4) * 2), loss='binary_crossentropy', metrics=['accuracy']),但是我不知道我是否需要它。

我是否需要创建模型并编译它以从图像中提取特征


Tags: namesizenetlayerstfblockkerasrelu
2条回答

编译模型与否取决于您用于训练模型的方法,即:

如果使用model.fit,则需要在拟合模型之前编译模型

如果使用custom training,则不必返回模型并使用它,就像:

optimizer = tf.keras.optimizers.Adam(lr=(1e-4) * 2)
bce = tf.keras.losses.BinaryCrossentropy()

tf.GradientTape() as tape:
    y_pred = model(X)
    loss = bce(y_true, y_pred)

grads = tape.gradient(loss , model.trainable_variables)
optimizer.apply_gradients(zip(grads , model.trainable_variables))

使用keras API培训网络主要有两种方式:

  • 使用fit方法
  • 从头开始编写自定义循环

在这两种情况下,如果使用kerasAPI,则需要创建一个模型,它是连接层的集合

让我们使用keras定义一个简单的MLP(多层感知器)模型:

import tensorflow as tf

inp = tf.keras.Input((1,))
hidden = tf.keras.layers.Dense(10, activation="tanh")(inp)
out = tf.keras.layers.Dense(1, activation="simgoid")(hidden)
model = tf.keras.Model(inputs=inp, outputs=out)

让我们也生成一些简单的合成数据

x = tf.random.normal((100,1))
y = 2*x + 1

请注意,将MLP用于像这样简单的回归是过分的。简单的线性回归就足够了

使用fit

如果要使用fit方法,则需要编译模型。 编译模型类似于提供模型的训练策略:使用哪个目标函数(损失),使用哪个优化算法

在这种情况下,让我们使用一个简单的均方误差作为损失,SGD作为优化算法。完成后,您只需对数据调用fit

>>> model.compile(optimizer="sgd", loss="mse")
>>> model.fit(x,y)
4/4 [==============================] - 0s 2ms/step - loss: 4.5469

fit方法提供了很多选项,您可以通过查看documentation来探索它们

从头开始编写培训循环

有时,使用拟合方法不够灵活。在这种情况下,可以通过编写训练循环从头开始训练模型。在这种情况下,您需要自己定义所有内容。如果我想使用SDG作为优化器和均方误差损失函数,我可以这样做:

opt = tf.optimizers.SGD()
for data,label in zip(x,y):
    with tf.GradientTape() as tape:
        pred = model(data)
        loss = tf.losses.mse(pred,label)
    grad = tape.gradient([loss], model.weights)
    opt.apply_gradients(zip(grad, model.weights))

这种方法更灵活,但也更冗长。在这种情况下,我不需要编译模型。编译只是使优化器和loss函数适合method的方法

进一步阅读

您可以阅读更多关于:

相关问题 更多 >