首页 > 其他分享 >猫狗笔记注释2

猫狗笔记注释2

时间:2023-08-09 23:01:06浏览次数:53  
标签:fc1 nn conv 卷积 张量 笔记 注释 tf

# coding: utf-8

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import time
import create_and_read_TFRecord2 as reader2
import os

X_train, y_train = reader2.get_file("c:\\cat_and_dog_r")#名为reader2的对象,通过get_file方法来获取指定路径下的训练数据。函数返回的X_train是训练数据集,y_train是对应的标签。
#返回一个包含图像批次和标签批次的元组(image_batch, label_batch),用于训练模型。确保传递正确的图像数据集和标签数据集,并根据需要调整图像和批次的大小和维度参数。
image_batch, label_batch = reader2.get_batch(X_train, y_train, 227, 227, 200, 2048)#从X_train和y_train数据集中获取一个批次的图像和标签数据,图像的宽度(假设是227像素)图像的高度(假设是227像素)批次大小(假设为200)特征维度(假设为2048)

#函数的目的是进行批归一化操作,它可以有效地加速模型的训练过程并提高模型的泛化能力。在训练模式下,它会对输入进行标准化,并根据输入的均值和方差对输入进行缩放和平移,使得输入的分布更加稳定。在测试模式下,它会使用跟踪的滑动平均值进行标准化。
def batch_norm(inputs, is_training,is_conv_out=True,decay = 0.999):#一个批归一化(Batch Normalization)的函数batch_norm inputs:输入的张量(tensor) is_training:一个布尔值,指示当前是否为训练模式 is_conv_out:一个布尔值,指示输入是否为卷积层输出。默认为True 。 decay:衰减参数(decay),用于计算滑动平均(moving average)。默认值为0.999。
#义了一个scale变量,它是一个形状与inputs张量最后一个维度相同的向量,并且所有元素的初始值都为1。在批归一化操作中,scale用于缩放标准化后的输入。
scale = tf.Variable(tf.ones([inputs.get_shape()[-1]]))#使用了tf.Variable函数来创建一个可训练的变量,并通过tf.ones函数初始化为一个全为1的向量。inputs.get_shape()[-1]用于获取inputs张量的最后一个维度的大小,这个值也就是批归一化中需要缩放的维度数。
beta = tf.Variable(tf.zeros([inputs.get_shape()[-1]])) #使用了tf.Variable函数来创建一个可训练的变量,并通过tf.zeros函数初始化为一个全为0的向量。inputs.get_shape()[-1]用于获取inputs张量的最后一个维度的大小,这个值也就是批归一化中需要平移的维度数。
pop_mean = tf.Variable(tf.zeros([inputs.get_shape()[-1]]), trainable=False)#定义了一个pop_mean变量,它是一个形状与inputs张量最后一个维度相同的向量,并且所有元素的初始值都为0。这里使用了trainable=False参数,将该变量设置为不可训练的。
pop_var = tf.Variable(tf.ones([inputs.get_shape()[-1]]), trainable=False)#pop_var是用于跟踪整个训练集的方差。在批归一化中,它用于计算滑动平均的方差,并在测试阶段使用这个方差进行标准化操作。

if is_training: # 如果is_training条件为真,表示当前处于训练阶段,可以执行相关的操作。 在批归一化中,训练阶段需要进行一些额外的操作,如计算当前批次的均值和方差,并更新整个训练集的滑动平均值。这些操作有助于模型更好地适应训练数据。
if is_conv_out: #如果is_conv_out条件为真,表示当前处于卷积层的输出。在卷积层的输出上进行操作时,可以执行一些特定于卷积层的操作。
batch_mean, batch_var = tf.nn.moments(inputs,[0,1,2]) #使用了tf.nn.moments函数来计算inputs张量的均值(batch_mean)和方差(batch_var)。第二个参数[0,1,2]表示沿着维度0、1和2进行计算。 用于计算卷积层或批归一化层的均值和方差。在卷积层中,输入张量通常具有4个维度:[batch_size, height, width, channels]。沿着维度0、1和2计算均值和方差,可以得到每个通道的统计信息。
else:
batch_mean, batch_var = tf.nn.moments(inputs,[0]) #使用了tf.nn.moments函数来计算 inputs 张量的均值 batch_mean 和方差 batch_var。第二个参数 [0] 表示沿着维度 0 进行计算,即沿着批次维度计算均值和方差。
#这段代码的实现逻辑是,根据给定的衰减系数 decay 和当前批次的均值 batch_mean,计算出新的均值 train_mean。这里使用了滑动平均的方式更新整个训练集的均值,通过将当前均值与历史均值加权平均来得到新的均值。较小的衰减系数 decay 会使得历史均值的影响逐渐降低,同时增加了当前批次均值的权重。
train_mean = tf.assign(pop_mean,
pop_mean * decay + batch_mean * (1 - decay))#使用了 TensorFlow 的 tf.assign 函数,将计算得到的新的均值值 train_mean 赋值给 pop_mean 变量。pop_mean 是一个 TensorFlow 变量,表示整个训练集的均值。通过 tf.assign 函数可以将新的均值 train_mean 赋值给 pop_mean 变量,更新整个训练集的均值。
train_var = tf.assign(pop_var,
pop_var * decay + batch_var * (1 - decay))#pop_var 是一个 TensorFlow 变量,表示整个训练集的方差。通过 tf.assign 函数可以将新的方差 train_var 赋值给 pop_var 变量,更新整个训练集的方差。
with tf.control_dependencies([train_mean, train_var]): #tf.control_dependencies 是 TensorFlow 中用于定义操作之间的依赖关系的上下文管理器。在这个特定的代码片段中,train_mean 和 train_var 都是通过 tf.assign 函数进行赋值操作得到的新的均值和方差。
return tf.nn.batch_normalization(inputs,
batch_mean, batch_var, beta, scale, 0.001)#使用了 TensorFlow 的 tf.nn.batch_normalization 函数来进行批归一化操作并返回归一化后的结果。inputs:待归一化的张量。batch_mean:每个特征的批次均值。batch_var:每个特征的批次方差。beta:偏置项,用于调整归一化后的结果。scale:缩放因子,用于调整归一化后的结果。variance_epsilon:用于增加稳定性的小值。
else:
return tf.nn.batch_normalization(inputs,
pop_mean, pop_var, beta, scale, 0.001)#函数会根据提供的整个训练集的均值、整个训练集的方差、偏置项和缩放因子,对输入张量 inputs 进行归一化,计算公式与之前相同。最后,函数返回归一化后的结果。这种批归一化的方式通常用于深度学习中的训练过程中,有助于加速训练和提高模型的泛化能力。

with tf.device('/cpu:0'): #tf.device 函数来指定操作在计算图中的设备位置。在这个特定的代码片段中,设备位置被指定为 /cpu:0,表示将操作放在第一个 CPU 设备上执行。
# 模型参数
learning_rate = 1e-4 #这行代码定义了学习率 learning_rate,并将其设定为 1e-4,即 0.0001。 学习率是深度学习中的一个重要超参数,它决定了在每次参数更新时,更新的步长大小。较小的学习率可以使训练过程更稳定,但可能需要更多的迭代次数才能收敛到最优解。较大的学习率可能会导致训练过程不稳定,甚至无法收敛。选择合适的学习率通常需要通过实验和调优来确定。常见的做法是尝试不同的学习率,并观察模型在训练过程中的表现。如果发现模型无法收敛或者在训练过程中出现震荡,则可能需要调整学习率。学习率被设定为 1e-4,这是一种常见的学习率初始值设置,可以根据具体问题和实验进行调整。
training_iters = 200 #这行代码定义了训练迭代次数 training_iters,并将其设定为 200。训练迭代次数表示在训练过程中重复执行训练步骤的次数。在深度学习中,模型的参数通常通过梯度下降法进行更新。每次迭代中,模型会根据当前的参数和训练数据计算出梯度,并根据学习率更新参数。训练迭代次数决定了我们要执行多少次这样的更新步骤。一般来说,增加训练迭代次数可以提高模型的性能,因为模型有更多机会从训练数据中学习到更好的表示。但是,迭代次数过多也可能导致过拟合,即模型在训练数据上表现良好,但在未见过的数据上泛化能力较差。
batch_size = 200 #行代码定义了批次大小 batch_size,并将其设定为 200。批次大小(Batch Size)表示在训练过程中每次输入给模型的样本数量。在这个代码片段中,批次大小被设定为 200,即每次模型更新时会使用 200 个样本进行训练。具体的批次大小选择需要根据问题的复杂度、可用的计算资源和内存容量进行调整。较大的批次大小可能会加快训练速度,但也会增加内存需求。较小的批次大小可能会加强梯度计算的准确性,但可能会导致训练过程的震荡。因此,选择合适的批次大小需要进行实验和调优。
display_step = 5 #定义了显示步长 display_step,并将其设定为 5。显示步长表示在训练过程中每隔多少个批次就显示一次训练信息或评估结果。显示步长被设定为 5,意味着在每隔 5 个批次之后就会显示一次训练信息或评估结果。具体的显示步长可以根据需要进行调整。较小的显示步长可以提供更频繁的更新信息,但可能会增加训练过程中显示的次数。较大的显示步长可能会减少显示次数,但同时也会减少训练过程中的信息更新频率。
n_classes = 2 #定义了类别数量 n_classes,并将其设定为 2。类别数量表示在分类任务中要预测的不同类别的个数。在分类任务中,我们需要区分不同的类别并预测每个样本所属的类别。类别数量取决于具体的问题和数据集,对于二分类问题,类别数量通常为2,表示样本可以属于两个不同的类别。常见的二分类问题包括判断邮件是垃圾邮件还是正常邮件、图像识别中的两类物体等。
n_fc1 = 4096#定义了第一个全连接层的神经元数量 n_fc1,并将其设定为 4096。全连接层是神经网络中的一种常见层类型,其中的每个神经元都与上一层的每个神经元相连接。在深度学习中,全连接层通常用于将高维的输入数据映射到更低维的表示,并且可以增加模型的非线性表达能力。全连接层的神经元数量决定了该层的输出维度,也就是特征的维度。
n_fc2 = 2048 #义了第二个全连接层的神经元数量 n_fc2,并将其设定为 2048。第二个全连接层是在第一个全连接层之后添加的另一个全连接层。多个全连接层的堆叠通常用于增加模型的复杂度和表达能力。每个全连接层都将上一层的输出作为输入,并使用一组可学习的权重和偏置来执行非线性变换。


# 构建模型
x = tf.placeholder(tf.float32, [None, 227, 227, 3])#创建了一个 TensorFlow 占位符(placeholder) x,并指定了它的数据类型为 tf.float32。它是一个四维的张量,形状为 [None, 227, 227, 3]。占位符 x 被定义为一个四维张量。形状的第一个维度使用 None 表示,这意味着可以接受任意数量的样本。第二和第三维度是 227,表示输入图像的宽度和高度为 227 像素。第四个维度是 3,表示输入图像是 RGB 彩色图像,具有 3 个通道。
y = tf.placeholder(tf.int32, [None, n_classes])#创建了一个 TensorFlow 占位符(placeholder) y,并指定了它的数据类型为 tf.int32。它是一个二维张量,形状为 [None, n_classes]。创建了一个 TensorFlow 占位符(placeholder) y,并指定了它的数据类型为 tf.int32。它是一个二维张量,形状为 [None, n_classes]。

W_conv = {
'conv1': tf.Variable(tf.truncated_normal([11, 11, 3, 96], stddev=0.0001)), #W_conv 是一个字典,其中包含一个名为 'conv1' 的键,并且与之对应的值是一个 TensorFlow 变量。该变量通过使用 tf.Variable 来创建,并使用 tf.truncated_normal 来初始化。W_conv['conv1'] 是一个具有 [11, 11, 3, 96] 形状的四维张量 'conv1' 是一个卷积层的权重,其卷积核尺寸为 11x11,输入通道数为 3,输出通道数为 96。tf.truncated_normal 是一个用于生成截断正态分布随机数的函数,它的参数 stddev 指定了生成的随机数的标准差。
'conv2': tf.Variable(tf.truncated_normal([5, 5, 96, 256], stddev=0.01)), #W_conv['conv2'] 是一个具有 [5, 5, 96, 256] 形状的四维张量,其中每个维度的含义如下: 'conv2' 是另一个卷积层的权重,其卷积核尺寸为 5x5,输入通道数为 96,输出通道数为 256。
'conv3': tf.Variable(tf.truncated_normal([3, 3, 256, 384], stddev=0.01)), #
'conv4': tf.Variable(tf.truncated_normal([3, 3, 384, 384], stddev=0.01)),
'conv5': tf.Variable(tf.truncated_normal([3, 3, 384, 256], stddev=0.01)),
'fc1': tf.Variable(tf.truncated_normal([13 * 13 * 256, n_fc1], stddev=0.1)), #W_conv 字典中还有一个键 'fc1',与之对应的值是另一个 TensorFlow 变量。同样使用 tf.Variable 创建,并使用 tf.truncated_normal 进行初始化。W_conv['fc1'] 是一个具有 [13 * 13 * 256, n_fc1] 形状的二维张量,其中每个维度的含义如下:第一个维度 13 * 13 * 256:表示展平后的张量的长度。13是指前面卷积层输出的特征图的尺寸为 13x13,256 表示卷积层的输出通道数。第二个维度 n_fc1:表示全连接层(Fully Connected Layer)的神经元数量。这说明 'fc1' 是一个全连接层的权重,将展平(Flatten)后的特征图作为输入,并输出 n_fc1 个神经元。
'fc2': tf.Variable(tf.truncated_normal([n_fc1, n_fc2], stddev=0.1)), #W_conv['fc2'] 是一个具有 [n_fc1, n_fc2] 形状的二维张量,其中每个维度的含义如下:第一个维度 n_fc1:表示前一层全连接层的输出神经元数量。第二个维度 n_fc2:表示当前全连接层的输出神经元数量。'fc2' 是另一个全连接层的权重,将前一层全连接层的输出作为输入,并输出 n_fc2 个神经元。
'fc3': tf.Variable(tf.truncated_normal([n_fc2, n_classes], stddev=0.1)) #W_conv['fc3'] 是一个具有 [n_fc2, n_classes] 形状的二维张量,其中每个维度的含义如下:第一个维度 n_fc2:表示前一层全连接层的输出神经元数量。第二个维度 n_classes:表示最终输出的类别数量。
}
b_conv = {
'conv1': tf.Variable(tf.constant(0.0, dtype=tf.float32, shape=[96])), #W_conv['conv1'] 是一个具有长度为 96 的一维张量,形状为 [96]。'conv1' 是一个卷积层的权重,其中每个元素的值都被设置为 0.0。由于使用了 tf.constant,权重的值将保持不变。使用 tf.constant 进行初始化。
'conv2': tf.Variable(tf.constant(0.1, dtype=tf.float32, shape=[256])),
'conv3': tf.Variable(tf.constant(0.1, dtype=tf.float32, shape=[384])),
'conv4': tf.Variable(tf.constant(0.1, dtype=tf.float32, shape=[384])),
'conv5': tf.Variable(tf.constant(0.1, dtype=tf.float32, shape=[256])),
'fc1': tf.Variable(tf.constant(0.1, dtype=tf.float32, shape=[n_fc1])),#W_conv['fc1'] 是一个具有长度为 n_fc1 的一维张量,形状为 [n_fc1]。
'fc2': tf.Variable(tf.constant(0.1, dtype=tf.float32, shape=[n_fc2])),
'fc3': tf.Variable(tf.constant(0.0, dtype=tf.float32, shape=[n_classes]))
}

x_image = tf.reshape(x, [-1, 227, 227, 3]) #x_image 是一个经过重塑的张量,通过tf.reshape函数被构建。-1 表示 TensorFlow 会自动计算该维度的大小,以确保与原始张量具有相同的元素数量。227 和 3 分别表示图像的高度、宽度和通道数,对应着一个 227x227 像素的 RGB 图像,其中颜色通道为 3 (红、绿、蓝)。

# 卷积层 1
conv1 = tf.nn.conv2d(x_image, W_conv['conv1'], strides=[1, 4, 4, 1], padding='VALID')#conv1 是通过使用 tf.nn.conv2d 函数对重塑后的输入张量 x_image 进行卷积操作得到的。卷积操作使用了名为 'conv1' 的权重张量 W_conv['conv1'],卷积操作的步长为 [1, 4, 4, 1],填充模式设置为 'VALID'。strides=[1, 4, 4, 1] 表示卷积操作在输入张量的四个维度上的步长分别为 [1, 4, 4, 1]。在这个设置下,卷积操作将在高度和宽度维度上以步长为 4 进行卷积操作,而在输入张量的其他维度上不进行步长操作。padding='VALID' 表示卷积操作的填充模式为 'VALID',意味着不进行边界填充。
conv1 = tf.nn.bias_add(conv1, b_conv['conv1'])#conv1 是通过对卷积结果 conv1 应用偏置值进行调整后得到的。bias_add 函数用于将偏置项 b_conv['conv1'] 加到 conv1 上。偏置项是一个与卷积层输出通道数相等的一维张量。通过将偏置项加到卷积结果上,可以引入偏置值的调整,以便在模型中引入偏移量的概念。这有助于模型更好地适应数据和进行更准确的预测。最后,调整后的结果将作为下一层的输入进行进一步的处理。
conv1 = tf.nn.relu(conv1)#conv1 是通过应用修正线性单元(ReLU)激活函数对卷积结果 conv1 进行激活操作得到的。在 TensorFlow 中,tf.nn.relu() 函数用于实现 ReLU 激活函数。ReLU 函数将所有负值设置为零,而保留所有非负值不变。通过应用 ReLU 激活函数,负值将被压缩为零,而非负值将保持不变。这有助于引入非线性特性和非线性变换,从而使模型能够学习更复杂的函数关系。激活后的结果 conv1 将成为下一层的输入,以供进一步的处理。
# 池化层 1
pool1 = tf.nn.avg_pool(conv1, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='VALID')#ool1 是通过使用均值池化操作对激活后的张量 conv1 进行下采样得到的。avg_pool 函数用于实现均值池化操作。均值池化通过在输入张量的局部区域内计算平均值来降低空间分辨率。ksize=[1, 3, 3, 1] 参数用于指定池化窗口大小,在这里窗口大小为 3x3,表示在高度和宽度维度上都使用一个大小为 3x3 的窗口。strides=[1, 2, 2, 1] 参数表示在输入张量的四个维度上的步长分别为 [1, 2, 2, 1]。这意味着均值池化操作在高度和宽度维度上以步长为2进行下采样,而在输入张量的其他维度上不进行步长操作。padding='VALID' 表示池化操作的填充模式为 'VALID',即不进行边界填充。通过均值池化操作,pool1 将成为下一层的输入,从而将空间分辨率降低一半,同时保留重要的特征。这有助于减少模型中的参数数量并提取更为显著的特征,以便进行更有效的模式识别和特征表示。
# LRN层,Local Response Normalization
norm1 = tf.nn.lrn(pool1, 5, bias=1.0, alpha=0.001 / 9.0, beta=0.75)#norm1 是通过使用局部响应归一化(LRN)操作对池化结果 pool1 进行处理得到的。lrn 函数用于实现局部响应归一化操作。局部响应归一化旨在模拟生物视觉系统中的侧抑制机制,它通过抑制活动较弱的神经元并增强活动较强的神经元来增强特征的对比度。pool1 是输入张量。5 是局部响应归一化的窗口大小。bias=1.0 是偏置项。alpha=0.001 / 9.0 是归一化的系数。beta=0.75 是指数。

#卷积层 2
conv2 = tf.nn.conv2d(norm1, W_conv['conv2'], strides=[1, 1, 1, 1], padding='SAME')#conv2 是通过对归一化结果 norm1 进行 2D 卷积操作得到的。conv2d 函数用于实现 2D 卷积操作。在此操作中,norm1 被与权重矩阵 W_conv['conv2'] 进行卷积运算。norm1 是输入张量。W_conv['conv2'] 是卷积核参数。strides=[1, 1, 1, 1] 表示在输入张量的四个维度上的步长分别为 [1, 1, 1, 1],表示在所有维度上进行步长为 1 的卷积操作。padding='SAME' 表示在卷积操作时,对输入张量进行零填充以保持与输出张量相同的尺寸。通过卷积操作,可以提取输入张量中的局部特征,并将其转换为输出张量。这有助于捕捉输入数据中的空间结构和模式。最后,conv2 将作为下一层的输入,以供进一步的处理和分析。
conv2 = tf.nn.bias_add(conv2, b_conv['conv2'])#conv2 是通过添加偏置项 b_conv['conv2'] 到 conv2 上得到的。在卷积操作之后,通常会添加一个偏置项,以便引入某种偏置或偏移量,从而更好地拟合数据。tf.nn.bias_add() 函数用于将偏置项添加到卷积结果上。该函数会自动对偏置项进行广播,以与卷积结果的形状相匹配。添加偏置项有助于模型更好地适应数据,为输出结果引入了一种偏移或平移的能力。这样可以提供更大的灵活性和表达能力,以便更好地拟合不同数据模式。最后得到的结果 conv2 将作为下一层的输入,供进一步的处理和分析。
conv2 = tf.nn.relu(conv2)#conv2 是通过应用 Rectified Linear Unit (ReLU) 激活函数对 conv2 进行操作得到的。
# 池化层 2
pool2 = tf.nn.avg_pool(conv2, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='VALID')#pool2 是通过应用平均池化操作对 conv2 进行处理得到的结果。平均池化是一种常用的池化操作,它将输入张量的每个区域(由 ksize 参数定义)中的元素取平均值,并生成一个降采样后的输出张量。tf.nn.avg_pool() 函数被用于对 conv2 进行平均池化操作。该函数的参数包括:conv2 是输入张量。ksize=[1, 3, 3, 1] 定义了池化窗口的大小,其中 [1, 3, 3, 1] 表示在输入张量的四个维度上的窗口大小分别为 [1, 3, 3, 1]。strides=[1, 2, 2, 1] 定义了在输入张量的四个维度上的池化窗口的步长,其中 [1, 2, 2, 1] 表示在水平和垂直方向上的步长为 2。padding='VALID' 表示不进行零填充,保持输出尺寸与输入尺寸的变化相适应。
# LRN层,Local Response Normalization
norm2 = tf.nn.lrn(pool2, 5, bias=1.0, alpha=0.001 / 9.0, beta=0.75)#norm2 = tf.nn.lrn(pool2, 5, bias=1.0, alpha=0.001 / 9.0, beta=0.75)局部响应归一化 (LRN) 是一种用于增强模型泛化能力的技术,它在特征图的每个位置上对邻近的特征进行归一化处理。tf.nn.lrn() 函数被用于对 pool2 进行局部响应归一化操作。pool2 是输入张量。5 表示归一化的窗口大小。bias=1.0 表示归一化时添加的偏置项。alpha=0.001/9.0 表示归一化中的比例因子。beta=0.75 表示归一化中的指数项。

# 卷积层3
conv3 = tf.nn.conv2d(norm2, W_conv['conv3'], strides=[1, 1, 1, 1], padding='SAME')#conv3 是通过使用卷积核 W_conv['conv3'] 对 norm2 进行卷积操作得到的结果。卷积操作是深度学习中常用的操作之一,它可以提取图像或特征图中的不同特征和模式。,tf.nn.conv2d() 函数被用于对 norm2 应用卷积操作。norm2 是输入张量。W_conv['conv3'] 是卷积核。strides=[1, 1, 1, 1] 定义了在输入张量的四个维度上的卷积步长,其中 [1, 1, 1, 1] 表示在每个维度上的步长为 1。padding='SAME' 表示进行零填充,使得输入和输出的尺寸保持一致。通过卷积操作,可以在输入张量中利用卷积核提取不同的特征。卷积核中的权重矩阵将从输入中滑动,并计算与输入相对应的位置的内积,从而得到输出张量 conv3。
conv3 = tf.nn.bias_add(conv3, b_conv['conv3'])#conv3 经过卷积操作后,通过使用偏置项 b_conv['conv3'] 进行偏置添加得到最终的结果。在卷积操作中,除了卷积核进行计算之外,还可以通过添加偏置项来引入偏置(常值)。这有助于模型更好地拟合数据,并引入对输入的线性偏移。tf.nn.bias_add() 函数被用于将 b_conv['conv3'] 偏置项添加到 conv3 中。conv3 是经过卷积操作得到的输出张量。b_conv['conv3'] 是与卷积操作对应的偏置项。通过偏置添加操作,可以为每个卷积操作的输出添加一个常值偏置,使得模型能够对输入数据进行更准确的建模和预测。

conv3 = tf.nn.relu(conv3)#conv3 经过偏置添加后,通过使用激活函数 ReLU 对其进行激活操作。ReLU(Rectified Linear Unit)是深度学习中常用的激活函数,它将所有负值都转换为零,而将正值保持不变。,tf.nn.relu() 函数被用于对 conv3 进行 ReLU 激活操作,将所有负值设为零。该激活函数不改变正值,且满足非线性的特性。

# 卷积层4
conv4 = tf.nn.conv2d(conv3, W_conv['conv4'], strides=[1, 1, 1, 1], padding='SAME')
conv4 = tf.nn.bias_add(conv4, b_conv['conv4'])
conv4 = tf.nn.relu(conv4)

# 卷积层5
conv5 = tf.nn.conv2d(conv4, W_conv['conv5'], strides=[1, 1, 1, 1], padding='SAME')
conv5 = tf.nn.bias_add(conv5, b_conv['conv5'])
conv5 = tf.nn.relu(conv2)

# 池化层5
pool5 = tf.nn.avg_pool(conv5, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='VALID')

reshape = tf.reshape(pool5, [-1, 13 * 13 * 256])#reshape 使用 tf.reshape() 函数对 pool5 进行形状重塑。其中的参数 [-1, 13 * 13 * 256] 表示将 pool5 转变为一个大小为 [batch_size, 13 * 13 * 256] 的二维张量,其中 batch_size 的值由输入张量的维度决定,而 13 * 13 * 256 则代表了 pool5 张量的总元素数量。

fc1 = tf.add(tf.matmul(reshape, W_conv['fc1']), b_conv['fc1'])#fc1 是通过对 reshape 进行矩阵乘法操作,并添加偏置项得到的结果。tf.matmul() 函数将 reshape 和 W_conv['fc1'] 进行矩阵乘法运算,得到一个新的张量。其中,reshape 是一个二维张量,大小为 [batch_size, 13*13*256],W_conv['fc1'] 是一个权重矩阵,用于连接 reshape 的每一列。这一乘法操作会生成一个 [batch_size, num_neurons] 大小的张量,其中 num_neurons 是 W_conv['fc1'] 的列数。tf.add() 函数将乘法结果与偏置项 b_conv['fc1'] 相加,得到最终的结果 fc1。偏置项的形状应该与 W_conv['fc1'] 的最后一维相匹配,以便相加。这个操作是全连接层的前向传播操作,将上一层的输出与权重矩阵相乘,并添加偏置项用于引入非线性。通过这样的操作,可以将低层级的特征映射转换为高层级的特征表示,用于进行后续的分类或者预测任务。
fc1 = tf.nn.relu(fc1)#fc1 是通过对 fc1 应用 ReLU 激活函数得到的结果。tf.nn.relu() 函数被用于对 fc1 进行 ReLU 激活操作,将所有负值设为零。这样的操作有助于引入非线性性质,帮助模型更好地学习和表示复杂的数据模式和特征。
fc1 = tf.nn.dropout(fc1, 0.5)#fc1 是通过对 fc1 进行 Dropout 操作得到的结果。Dropout 是深度学习中一种常用的正则化技术,用于减少模型的过拟合。它在网络的训练阶段,以一定的概率舍弃(将其置零)部分神经元的输出,从而使模型具有更好的泛化能力。tf.nn.dropout() 函数被用于对 fc1 进行 Dropout 操作,其中的参数 0.5 表示舍弃率为 50%,即会随机舍弃一半的神经元输出,将其置零。通过 Dropout 操作,可以减少模型之间的相互依赖性,提高模型的鲁棒性和泛化能力,一定程度上避免过拟合的发生。
# 全连接层 2
fc2 = tf.add(tf.matmul(fc1, W_conv['fc2']), b_conv['fc2'])
fc2 = tf.nn.relu(fc2)
fc2 = tf.nn.dropout(fc2, 0.5)
# 全连接层 3, 即分类层
fc3 = tf.add(tf.matmul(fc2, W_conv['fc3']), b_conv['fc3'])

# 定义损失
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(fc3, y))#tf.nn.softmax_cross_entropy_with_logits() 函数被用于计算模型输出 fc3 和实际标签 y 之间的 softmax 交叉熵损失。fc3 是模型的最后一层输出,形状应为 [batch_size, num_classes],其中 num_classes 是分类任务的类别数量。y 是实际的标签,形状应为 [batch_size, num_classes],与 fc3 保持一致。过 softmax 交叉熵损失函数的计算,可以度量模型输出与实际标签之间的差异,越大则表示模型预测的概率分布与实际目标之间的差异越大。tf.reduce_mean() 函数将计算得到的每个样本的交叉熵损失进行求平均,得到整个批次的平均损失。这是为了降低批次中样本数量的影响,并使损失对于不同批次的数据更具有可比性。
optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(loss)#optimizer 是通过使用梯度下降优化算法来最小化 loss 的结果。tf.train.GradientDescentOptimizer() 函数被用于创建一个梯度下降优化器,其中的 learning_rate 参数指定了学习率(learning rate),用于控制参数更新的步长大小。通过调用 .minimize(loss) 方法,调用优化器对目标函数 loss 进行最小化操作。梯度下降优化器会计算损失函数关于模型参数的梯度,然后按照学习率的设定,以此梯度的相反方向对模型参数进行更新,从而逐渐降低损失函数,并提高模型的性能。
# 评估模型
correct_pred = tf.equal(tf.argmax(fc3, 1), tf.argmax(y, 1))#correct_pred 是通过比较 fc3 预测输出和实际标签 y 的 argmax 值是否相等得到的结果。通过 tf.argmax(fc3, 1) 找到 fc3 在每个样本中预测输出的最大值所对应的索引,形状为 [batch_size]。同样地,使用 tf.argmax(y, 1) 找到实际标签 y 在每个样本中的最大值所对应的索引。这两个索引值进行比较,使用 tf.equal() 函数进行逐元素比较,返回布尔类型的张量。correct_pred 的结果是一个布尔类型的张量,表示模型在每个样本上的预测是否与实际标签相匹配。如果预测正确,则对应位置的值为 True,否则为 False。correct_pred 可以被用于计算模型的准确率(accuracy),通过计算预测正确的样本数量占总样本数量的比例来评估模型的性能。
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))#accuracy 是通过计算预测的正确率得到的结果。tf.cast(correct_pred, tf.float32) 被用于将 correct_pred 张量中的布尔值转换为浮点数类型,其中将 True 转换为 1.0,将 False 转换为 0.0。这个操作是为了将布尔类型的预测结果转换为可进行数值计算的形式。通过 tf.reduce_mean() 函数计算浮点数类型 correct_pred 的平均值,得到一个标量,表示模型整体的正确率。后得到的结果 accuracy 是一个标量,代表模型在给定数据集上的正确率。正确率是预测正确的样本数量与总样本数量的比例,它是评估模型性能的指标之一。数值范围在 0 到 1 之间,数值越高表示模型的预测越准确。

init = tf.global_variables_initializer()#tf.global_variables_initializer() 函数用于创建一个操作,该操作可以初始化所有的全局变量。全局变量是在模型中定义的可训练参数,如权重和偏置项等。在 TensorFlow 中,变量必须经过初始化后才能被使用。通过调用 tf.global_variables_initializer() 函数创建的 init 操作,可以在会话中运行,以便将所有全局变量初始化为初始值。通过执行 init 操作,可以在模型训练开始之前,将所有的全局变量初始化为预定的初始值,以确保模型的参数处于一个合适的状态,从而能够正确地进行训练和推断。

def onehot(labels): #onehot 是一个函数的定义,用于将标签数据进行独热编码(One-Hot Encoding)。通常,在机器学习和深度学习的任务中,标签数据是以整数形式表示的类别标签。而独热编码是一种将离散型特征进行向量化表示的方法,其中每个类别对应一个唯一的向量。
'''one-hot 编码'''
n_sample = len(labels)#len(labels) 是用于获取标签列表 labels 的长度,即其中元素的个数。通过获取列表的长度,可以确定标签数据的样本数量。,在机器学习和深度学习任务中,标签数据的样本数与训练样本的数目一致。这个样本数的信息可以用于后续的独热编码或其他数据处理操作。
n_class = max(labels) + 1#max(labels) 是用于获取标签列表 labels 中的最大值,即其中标签的最大类别编号。通过获取最大值,并在其基础上加 1,可以得到标签数据的类别数量。一般情况下,类别数量是由标签数据中唯一的类别标签确定的。通过对标签数据进行统计,可以获取类别数量,这对于训练分类模型是很重要的。在独热编码等操作中,类别数量的信息能够指导编码的向量维度的确定。
onehot_labels = np.zeros((n_sample, n_class))#onehot_labels 是一个多维数组,用于存储独热编码后的标签数据。np.zeros((n_sample, n_class)) 是使用 NumPy 库创建一个形状为 (n_sample, n_class) 的全零数组。其中,n_sample 是标签数据的样本数量,n_class 是标签数据的类别数量。通过初始化一个全零数组,可以为每个样本的独热编码预留空间。后续可以根据标签数据的实际取值,将对应位置上的元素设置为 1,实现独热编码的效果。
onehot_labels[np.arange(n_sample), labels] = 1#onehot_labels[np.arange(n_sample), labels] = 1 是将标签数据进行独热编码的操作。np.arange(n_sample) 是一个以 0 到 n_sample-1 的整数数组,表示样本的索引。labels 是原始的标签数据,是一个一维数组,存储了样本对应的类别标签。onehot_labels[np.arange(n_sample), labels] 表示根据样本的索引和对应的类别标签,选取 onehot_labels 数组中的相应位置的元素。将选中的元素设置为 1,表示进行独热编码。通过这种方法,可以将每个样本的类别标签用一个向量表示,其中只有对应类别的位置是 1,其余位置为 0。最终,onehot_labels 数组将包含独热编码后的标签数据。
return onehot_labels

save_model = ".//model//AlexNetModel.ckpt"#save_model 是用于指定保存模型的路径和文件名。".//model//AlexNetModel.ckpt" 表示要将模型保存在当前目录下的 model 文件夹中,并命名为 AlexNetModel.ckpt。
def train(opech): #你可能想要定义一个名为 train 的函数,它接受一个参数 epoch(可能是拼写错误),用于指定训练的轮数。
with tf.Session() as sess:#用 TensorFlow 框架来创建一个会话 (Session) 来执行计算图。with tf.Session() as sess: 这行代码用于创建一个 TensorFlow 会话对象,并将其保存到变量 sess 中。使用 with 语句可以确保在代码块执行完毕后自动关闭会话,释放资源。在这个会话对象中,你可以执行 TensorFlow 的计算图,运行模型的训练、推理或评估等操作。这只是一个会话对象的创建步骤,后续的代码可能包含模型的训练、数据的加载、训练迭代等内容
sess.run(init)#sess.run(init) 用于在 TensorFlow 会话 (sess) 中运行初始化操作 (init)。在 TensorFlow 中,变量需要在使用之前进行初始化。通常,会使用 tf.global_variables_initializer() 函数创建一个初始化操作,并将其传递给会话的 run() 方法来执行实际的初始化操作。

train_writer = tf.summary.FileWriter(".//log", sess.graph) # 输出日志的地方
saver = tf.train.Saver()

c = []
start_time = time.time()

coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
step = 0
for i in range(opech):
step = i
image, label = sess.run([image_batch, label_batch])

labels = onehot(label)

sess.run(optimizer, feed_dict={x: image, y: labels})
loss_record = sess.run(loss, feed_dict={x: image, y: labels})
print("now the loss is %f " % loss_record)

c.append(loss_record)
end_time = time.time()
print('time: ', (end_time - start_time))
start_time = end_time
print("---------------%d onpech is finished-------------------" % i)
print("Optimization Finished!")
saver.save(sess, save_model)
print("Model Save Finished!")

coord.request_stop()
coord.join(threads)
plt.plot(c)
plt.xlabel('Iter')
plt.ylabel('loss')
plt.title('lr=%f, ti=%d, bs=%d' % (learning_rate, training_iters, batch_size))
plt.tight_layout()
plt.savefig('cat_and_dog_AlexNet.jpg', dpi=200)

from PIL import Image

def per_class(imagefile):

image = Image.open(imagefile)
image = image.resize([227, 227])
image_array = np.array(image)

image = tf.cast(image_array,tf.float32)
image = tf.image.per_image_standardization(image)
image = tf.reshape(image, [1, 227, 227, 3])

saver = tf.train.Saver()
with tf.Session() as sess:

save_model = tf.train.latest_checkpoint('.//model')
saver.restore(sess, save_model)
image = tf.reshape(image, [1, 227, 227, 3])
image = sess.run(image)
prediction = sess.run(fc3, feed_dict={x: image})

max_index = np.argmax(prediction)
if max_index==0:
return "cat"
else:
return "dog"

标签:fc1,nn,conv,卷积,张量,笔记,注释,tf
From: https://www.cnblogs.com/dq0618/p/17619022.html

相关文章

  • 【学习笔记】线段树分治
    定义线段树分治是一种解决一类有插入、删除和整体查询操作的问题的方法。它是一种离线做法,通过在线段树上记录操作的时间区间来处理修改对询问的影响。每个操作被看作一个时间区间的修改,并在线段树上进行标记。然后通过深度优先搜索(DFS)依次执行这些操作,直到根节点来回答查询,并在......
  • 做题笔记
    [AT_abc313_d]OddorEven简单题,但是为什么赛场上WA了呢?弱化题目,设\(n=k+1\),发现只需要每一个数不取询问\(k\)次,通过前缀和得出。再设\(k+1\|\n\),发现只需要类似分块即可解决。回到原题,最后的一部分如何计算?我们可以对\([n-k,n]\)这个区间做询问,但是对......
  • openGauss学习笔记-35 openGauss 高级数据管理-ALTER TABLE语句
    openGauss学习笔记-35openGauss高级数据管理-ALTERTABLE语句修改表,包括修改表的定义、重命名表、重命名表中指定的列、重命名表的约束、设置表的所属模式、添加/更新多个列、打开/关闭行访问控制开关。35.1语法格式在一张已经存在的表上添加列。ALTERTABLEtable_name......
  • [刷题笔记] Luogu P1280 尼克的任务
    ProblemAnalysis首先,如果一个时间只有一个任务开始,则她必须做。如果一个时间有多个任务开始,她可以选一个去做。我们发现这样的决策是取决于后面的空暇时间,而不是前面。所以在dp的时候需要从后往前搜时间(当然如果从前往后可以跑记搜)考虑转移,如果一个时间有多个任务开始,则选一个......
  • 【转录】卡片笔记法:从卢曼卡片盒到ANTINET
    在我们探讨卢曼卡片盒的使用成本时,我们发现真正的成本不仅在于时间投入,更在于个体面临的认知挑战。而当我们探讨ANTINET与双链笔记法的对比时,我们看到了信息组织方式的转变,从相对混沌的状态走向更加秩序化的分叉结构。然而,这种转变不仅限于信息的组织,更包括了我们笔记工具的选择:......
  • MySQL数据库笔记(一)
    第一章数据库概述1、什么是数据库数据库是一种存储并管理数据的软件系统存储:持久化管理:增删改查常用的存储数据的方式:1、Java中的变量:生命周期短,不能实现持久化[内存]2、序列化:管理数据时依赖于Java中的反序列化[硬盘]3、txt,办公软件:没有统一的方式管理数据[硬盘]4......
  • 主成分分析(PCA)模型学习笔记(一)
    目录为什么使用PCA从过拟合说起维度灾难模型定义PCA的两种推导数据准备最大投影方差最小重构距离小结为什么使用PCA从过拟合说起在数据量小、数据维度高,模型较为复杂时,很容易产生过拟合。训练误差小而泛化误差较大被称为过拟合,而我们所追求的是泛化误差较小,为了解决过拟合问题,......
  • 线性判别分析(LDA)模型笔记
    目录模型概况模型定义模型求解模型概况线性判别方法(LinearDiscriminationAnalysis)是一种经典的线性学些方法,最早由Fisher提出,也叫“Fisher判别分析”。LDA的思想非常朴素,也即是,将样例投影到一条直线上使得同类样例的投影点尽可能近,异类样例的投影点尽可能远,总结六个字就是......
  • avue-crud属性配置项参数笔记分享
     Avue是一个基于Element-plus低代码前端框架,它使用JSON配置来生成页面,可以减少页面开发工作量,极大提升效率;虽然Avue官网上面都有这些配置说明,但是如果刚开始接触不熟悉框架的话需要很久才找到自己需要的参数配置,为了方便自己今后查找使用,现将一些开发中常用的配置梳理在下......
  • Rocky9 编译安装 Nginx Mariadb Asp.net Core6 (实测 笔记)
    引用 https://www.cnblogs.com/vicowong/p/16974219.html一、查看硬件信息1、查看物理cpu个数、核心数量、线程数grep'physicalid'/proc/cpuinfo|sort-u|wc-lgrep'coreid'/proc/cpuinfo|sort-u|wc-lgrep'processor'/proc/cpuinfo|sort-u|wc......