【机器学习小记】【卷积神经网络模型】deeplearning.ai course4 1st week programming(tensorflow2.0实现)

本文讲解了如何使用TensorFlow 2.0搭建卷积神经网络模型,包括边界填充、单步卷积、卷积操作、池化层以及反向传播的基本原理。通过实例展示了如何初始化参数、前向传播、计算成本,并构建模型进行训练和预测,讨论了相关库的使用和调整,如数据格式、padding等关键概念。

目标:
	搭建简单的 卷积神经网络
	修改【参考文章】的代码,使用tensorflow2实现

参考自:【中文】【吴恩达课后编程作业】Course 4 - 卷积神经网络 - 第一周作业 - 搭建卷积神经网络模型以及应用(1&2)

1.3.1 边界填充

边界填充的作用:

  1. 卷积之后,保持了高度和宽度
  2. 卷积的时候,保留了更多的边界的信息(如果不使用pad填充,边界只会计算1次)

np.pad

np.pad(
	input,
	(npx,npy), # 样本数填充
	(hpx,hpy), # 图像高度填充
	(wpx,wpy), # 图像宽度填充
	(cpx,cpy),# 通道填充
	mode, # 填充模式constant表示常量填充
	constant_value # 填充的常量值
)

1.3.2 单步卷积

一步卷积,就是【一个窗口slice与过滤器W】 对应相乘再全部相加

1.3.3 卷积

卷积操作是对所有通道同时进行操作的

卷积之后的输出结果为:
n H [ l ] = ⌊ n H [ l − 1 ] − f [ l ] + 2 ⋅ p [ l ] s [ l ] ⌋ + 1 n_H^{[l]} = \lfloor {n_{H}^{[l-1]}- f^{[l]} + 2 \cdot p^{[l]} \over s^{[l]}} \rfloor +1 nH[l]=s[l]nH[l1]f[l]+2p[l]+1

n W [ l ] = ⌊ n W [ l − 1 ] − f [ l ] + 2 ⋅ p [ l ] s [ l ] ⌋ + 1 n_W^{[l]} = \lfloor {n_{W}^{[l-1]}- f^{[l]} + 2 \cdot p^{[l]} \over s^{[l]}} \rfloor +1 nW[l]=s[l]nW[l1]f[l]+2p[l]+1

n C = 过 滤 器 数 量 n_C = 过滤器数量 nC=
其中, n H , n W n_H,n_W nH,nW表示图像的高度宽度 [ l ] ^{[l]} [l]表示层数,f表示过滤器的大小,p表示图像填充多少,s表示卷积步长

1.4 池化层

池化的作用:

  1. 减少输入宽度和高度,进而减少之后的计算量
  2. 使特征检测器对其在输入中的位置更加稳定

池化分两种:

  1. 最大池化:取窗口中的最大值作为输出
  2. 平均池化:取窗口中所有值的平均值作为输出

池化之后输出的大小,和卷积类似,但是,池化一般不使用padding

1.5 反向传播

反向传播由框架搞定了,这里不写了

2.1.0 TensorFlow模型

模型大致如下:
CONV2D→RELU→MAXPOOL→CONV2D→RELU→MAXPOOL→FULLCONNECTED

import time
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import cnn_utils

import os

# 不使用GPU
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"

np.random.seed(1)
# 加载数据
def get_data():
    X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = cnn_utils.load_dataset()

    # index = 6
    # plt.imshow(X_train_orig[index])
    # print("y = " + str(np.squeeze(Y_train_orig[:, index])))
    # plt.show()
    """
        X_train_orig 是 1080*64*64*3的矩阵
    """
    # 归一化数据
    X_train = X_train_orig / 255
    X_test = X_test_orig / 255

    # Y转换成的独热码的形式
    Y_train = cnn_utils.convert_to_one_hot(Y_train_orig, 6).T
    Y_test = cnn_utils.convert_to_one_hot(Y_test_orig, 6).T

    return X_train, Y_train, X_test, Y_test, classes

不需要创建placeholders


2.1.1 初始化参数

原博文中说,【我们不需要考虑偏置值b,TensorFlow会考虑到】。但是,是否真的有考虑到,我没有深究。

def initialize_parameters():
    """
    初始化权值矩阵,这里我们把权值矩阵硬编码:
    W1 : [4, 4, 3, 8]
    W2 : [2, 2, 8, 16]
	W3 : [64,6]
	b3 : [1]
    返回:
        包含了tensor类型的W1、W2的字典
    """
    tf.random.set_seed(1)

    # 初始化器
    initializer = tf.initializers.he_uniform(0)

    # f=4x4,channel=3,n_c=8
    W1 = tf.Variable(initializer([4, 4, 3, 8]), name="W1")
    # f=2x2,channel=8,n_c=16
    W2 = tf.Variable(initializer([2, 2, 8, 16]), name="W2")

    # 全连接层参数
    W3 = tf.Variable(initializer([64, 6]),name="W3")
    b3 = tf.Variable(initializer([1]),name="b3")

    parameters = {
        "W1": W1,
        "W2": W2,
        "W3": W3,
        "b3": b3
    }
    return parameters

这里和原博文不同的是,需要手动添加上全连接层的参数,方便后面使用求导和反向传播更新参数。


PS:当然,如果使用full_connection_layer = tf.keras.layers.Dense(6, activation=None)创建一个全连接层。Z3 = full_connection_layer(P)也可以实现全连接层的前向传播,后面可用使用full_connection_layer.variables获得本层全连接的参数,但是不方便,还不如自己写。(我还以为,如果在【自动求导】中,前向传播使用这个,后面求导的时候tensorflow会自动考虑上这个参数的更新。实际上,不会,还是要自己手动添加该层的参数,进行求导和参数更新。卡bug了一晚上。


测试:

parameters = initialize_parameters()
print("W1 = " + str(parameters["W1"].numpy()[1,1,1]))
print("W2 = " + str(parameters["W2"].numpy()[1,1,1]))
print("W3 = " + str(parameters["W3"].numpy()[1,1]))
print("b3 = " + str(parameters["b3"].numpy()))

输出:

W1 = [-0.10238287  0.35137287 -0.023274    0.00264338  0.00247917 -0.05561143
 -0.21562235 -0.27392948]
W2 = [-0.29680836  0.1650249  -0.12899727 -0.03889439  0.42350248 -0.11916256
  0.3731927  -0.15247756 -0.28602475 -0.3382344  -0.39762798  0.27272776
  0.22672692 -0.21311466 -0.09157833  0.05948022]
W3 = -0.18558505
b3 = [-1.4157294]

2.1.2 前向传播

def forward_propagation(X, parameters):
    """
    实现前向传播
    CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED
    参数:
        X - 维度为(样本数量,高度,宽度,通道数)
        parameters - 包含了“W1”、“W2”、”W3“、”b3“的python字典。

    返回:
        Z3 - 最后一个LINEAR节点的输出
    """
    # 获得参数
    W1 = parameters["W1"]
    W2 = parameters["W2"]
    W3 = parameters["W3"]
    b3 = parameters["b3"]
    """
        Z1.shape (64, 64, 64, 8)
        P1.shape (64, 8, 8, 8)
        Z2.shape (64, 8, 8, 16)
        P2.shape (64, 2, 2, 16)
    """
    # conv2d: s=1,pad=same
    Z1 = tf.nn.conv2d(X, W1, strides=[1, 1, 1, 1], padding="SAME")
    # relu
    A1 = tf.nn.relu(Z1)
    # max pool: f=8x8 s=8
    P1 = tf.nn.max_pool(A1, ksize=[1, 8, 8, 1], strides=[1, 8, 8, 1], padding="SAME")

    # conv2d s=1,pad=same
    Z2 = tf.nn.conv2d(P1, W2, strides=[1, 1, 1, 1], padding="SAME")
    # relu
    A2 = tf.nn.relu(Z2)
    # max pool: f=4x4 s=4
    P2 = tf.nn.max_pool(A2, ksize=[1, 4, 4, 1], strides=[1, 4, 4, 1], padding="SAME")

    # 拉平
    P = tf.reshape(P2, (P2.shape[0], -1))
    # out:64x64  样本数x维度

    # 全连接层:使用没有非线性激活函数的全连接层
    # full_connect_model = tf.keras.layers.Dense(6, activation=None)
    # Z3 = full_connect_model(P)
    Z3 = tf.matmul(P,W3) + b3
    # out:64x6

    return Z3
  • 注意此时的输入X的形状 (样本数量,高度,宽度,通道数)

  • 池化之后的输出的大小(padding的原因,详细见后面的padding),也和吴恩达老师定义的稍微有点不同。

  • 这里,手动实现了全连接层。
    Z3 的维度是(样本数,x)

测试:

X = np.random.randn(2,64,64,3)
parameters = initialize_parameters()
Z3 = forward_propagation(X,parameters)
print("Z3 = ",Z3)

输出:

Z3 =  tf.Tensor(
[[-1.9189914  5.236899  -2.1311748 -4.4184475 -3.7767754 -3.9814925]
 [-1.3195286  4.619976  -2.6811643 -5.2443013 -3.3180122 -3.3682647]], shape=(2, 6), dtype=float32)

2.1.3 计算成本

def compute_cost(Z3, Y):
    """
    计算成本
    参数:
        Z3 - 正向传播最后一个LINEAR节点的输出,维度为(样本数,6)。
        Y - 和Z3的维度相同
    返回:
        cost - 计算后的成本
    """

    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=Z3, labels=Y))

    return cost

测试:

X = np.random.randn(4,64,64,3)
Y = np.random.randn(4,6)
parameters = initialize_parameters()
Z3 = forward_propagation(X,parameters)
print("Z3 =",Z3)
print("Y =",Y,Y.shape)
cost = compute_cost(Z3,Y)
print("cost =",cost)

输出:

Z3 = tf.Tensor(
[[-1.9189913   5.2368994  -2.1311746  -4.418448   -3.7767758  -3.981492  ]
 [-1.3195288   4.619976   -2.6811643  -5.244302   -3.3180122  -3.3682647 ]
 [-1.1359475   4.538566   -2.0724049  -5.7774     -3.6145096  -3.2256317 ]
 [-2.8010159   5.0077     -0.25371218 -4.8593636  -3.7319794  -2.9729443 ]], shape=(4, 6), dtype=float32)
Y = [[-0.3153977   1.24542971 -1.30459226 -1.25915944  0.48752929 -0.24841797]
 [-1.28537295  2.04446858  0.14148981  1.33236812  1.26680127  0.90926308]
 [-0.44260544  0.73702333 -0.93976884  0.90032918 -0.29123109 -1.58389475]
 [ 0.05890907  0.37748493  1.84972109 -0.42243608 -0.32072321 -0.89134773]] (4, 6)
cost = tf.Tensor(-4.0131383, shape=(), dtype=float32)

注:

  • Z3的维度和原博文相反。
  • 在tensorflow中,一般按照每一行(行向量,每个样本就是一行)计算。

2.1.4 构建模型

预测函数

def predict(X_train, Y_train, X_test, Y_test, parameters):
    ##################################### 训练集
    # 预测值
    Z = forward_propagation(X_train, parameters) # out: 样本*dims
    # 找到最大值的下标,在向量行中找最大值的索引
    Z = tf.argmax(Z, axis=1)
    # 转换成独热码的形式
    # axis表示填充方向,行填充
    Z = tf.one_hot(Z, depth=Y_train.shape[1], axis=1)
    # 强制类型转换,和需要比较的标签的类型一致
    Z = tf.cast(Z, dtype=Y_train.dtype)

    # 预测值 与 真实值进行【比较】,强转成默认的int类型,我这里是int64
    # 得到一个True,False数组
    correct = tf.equal(Z, Y_train)

    # 强转,把bool数组转换成int数组
    correct = tf.cast(correct, dtype=tf.int64)
    # 求每一行的平均数,
    correct = tf.reduce_mean(correct, axis=1)
    # 强转,避免产生小数
    correct = tf.cast(correct, dtype=tf.int64)

    # 记录正确的数量,对所有元素求和
    total_correct = tf.reduce_sum(correct)
    # 样本数,这里是m
    total_number = X_train.shape[0]

    # 正确率 = 正确数 / 总样本数
    train_acc = total_correct / total_number
    print("训练集准确率:", train_acc.numpy())

    ################################## 预测集
    # 预测值
    Z = forward_propagation(X_test, parameters)
    # 找到最大值的下标,在向量行中找最大值的索引
    Z = tf.argmax(Z, axis=1)
    # 转换成独热码的形式
    # axis表示填充方向,行填充
    Z = tf.one_hot(Z, depth=Y_test.shape[1], axis=1)
    # 强制类型转换,和需要比较的标签的类型一致
    Z = tf.cast(Z, dtype=Y_test.dtype)

    # 预测值 与 真实值进行【比较】,强转成默认的int类型,我这里是int64
    # 得到一个True,False数组
    correct = tf.equal(Z, Y_test)

    # 强转,把bool数组转换成int数组
    correct = tf.cast(correct, dtype=tf.int64)
    # 求每一行的平均数,
    correct = tf.reduce_mean(correct, axis=1)
    # 强转,避免产生小数
    correct = tf.cast(correct, dtype=tf.int64)

    # 记录正确的数量,对所有元素求和
    total_correct = tf.reduce_sum(correct)
    # 样本数,这里是m
    total_number = X_test.shape[0]

    # 正确率 = 正确数 / 总样本数
    test_acc = total_correct / total_number
    print("测试集准确率:", test_acc.numpy())

    return train_acc, test_acc

由于输入矩阵进行了转置,和tensorflow2.0入门的作业稍微不一样

model

def model(X_train, Y_train, X_test, Y_test, learning_rate=0.009,
          num_epochs=100, mini_batch_size=64, print_cost=True, is_plot=True):
    """
    使用TensorFlow实现三层的卷积神经网络
    CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED
    参数:
        X_train - 训练数据,维度为(样本数, 64, 64, 3)
        Y_train - 训练数据对应的标签,维度为(样本数, n_y = 6)
        X_test - 测试数据,维度为(样本数, 64, 64, 3)
        Y_test - 训练数据对应的标签,维度为(样本数, n_y = 6)
        learning_rate - 学习率
        num_epochs - 遍历整个数据集的次数
        mini_batch_size - 每个小批量数据块的大小
        print_cost - 是否打印成本值,每遍历100次整个数据集打印一次
        is_plot - 是否绘制图谱
    返回:
        train_accuracy - 实数,训练集的准确度
        test_accuracy - 实数,测试集的准确度
        parameters - 学习后的参数
    """
    tf.random.set_seed(1)
    # 设置numpy的随机种子
    seed = 3
    m, n_H0, n_W0, n_C0 = X_train.shape
    n_y = Y_train.shape[1]

    costs = []

    # 初始化参数
    parameters = initialize_parameters()

    # 优化器
    optimizer = tf.optimizers.Adam(learning_rate=learning_rate)

    # 开始训练
    for epoch in range(num_epochs):
        # 每个epoch的成本
        epoch_cost = 0
        # mini_batch 的数量
        num_mini_batches = m // mini_batch_size

        # 每个epoch打乱batches
        seed = seed + 1
        mini_batches = cnn_utils.random_mini_batches(X_train, Y_train, mini_batch_size, seed)

        # 对于每个batch
        for step, (X, Y) in enumerate(mini_batches):
            with tf.GradientTape() as tape:
                # 前向传播
                Z3 = forward_propagation(X, parameters)

                # 计算成本
                mini_batch_cost = compute_cost(Z3, Y)

                epoch_cost = epoch_cost + mini_batch_cost / num_mini_batches

            # 获得梯度
            grads = tape.gradient(mini_batch_cost, list(parameters.values()))

            # 更新参数
            optimizer.apply_gradients(grads_and_vars=zip(grads, list(parameters.values())))

        # 打印成本
        if print_cost:
            costs.append(epoch_cost)
            if epoch % 5 == 0:
                print("当前是第 " + str(epoch) + " 代,成本值为:" + str(epoch_cost.numpy()))

    # 数据处理完毕,绘制曲线
    if is_plot:
        plt.plot(np.squeeze(costs))
        plt.ylabel("cost")
        plt.xlabel("iterations(per tens)")
        plt.title("learning rate =" + str(learning_rate))
        plt.show()

    train_accuracy, test_accuracy = predict(X_train, Y_train, X_test, Y_test,parameters)

    return parameters, train_accuracy, test_accuracy

测试

def main():
    X_train, Y_train, X_test, Y_test, classes = get_data()
    # 开始时间
    start_time = time.perf_counter()
    # 开始训练
    parameters = model(X_train, Y_train, X_test, Y_test, num_epochs=1000,learning_rate=0.009)
    # 结束时间
    end_time = time.perf_counter()
    # 计算时差
    print("CPU的执行时间 = " + str(end_time - start_time) + " 秒")
if __name__ == '__main__':
    main()

epoch=150,learning_rate=0.009,mini_batch_size=64

在这里插入图片描述

当前是第 0 代,成本值为:1.9711732
当前是第 5 代,成本值为:1.6441493
当前是第 10 代,成本值为:0.9809544
当前是第 15 代,成本值为:0.74599206
当前是第 20 代,成本值为:0.52382654
当前是第 25 代,成本值为:0.41984344
当前是第 30 代,成本值为:0.3410723
当前是第 35 代,成本值为:0.31803787
当前是第 40 代,成本值为:0.23219788
当前是第 45 代,成本值为:0.21172494
当前是第 50 代,成本值为:0.1985099
当前是第 55 代,成本值为:0.16930607
当前是第 60 代,成本值为:0.114748925
当前是第 65 代,成本值为:0.09465394
当前是第 70 代,成本值为:0.1167781
当前是第 75 代,成本值为:0.10553896
当前是第 80 代,成本值为:0.080426455
当前是第 85 代,成本值为:0.087554045
当前是第 90 代,成本值为:0.07595678
当前是第 95 代,成本值为:0.06289906
当前是第 100 代,成本值为:0.04345636
当前是第 105 代,成本值为:0.050669502
当前是第 110 代,成本值为:0.07043151
当前是第 115 代,成本值为:0.023179952
当前是第 120 代,成本值为:0.03279618
当前是第 125 代,成本值为:0.019446563
当前是第 130 代,成本值为:0.014923153
当前是第 135 代,成本值为:0.012299964
当前是第 140 代,成本值为:0.015927585
当前是第 145 代,成本值为:0.008962453
训练集准确率: 1.0
测试集准确率: 0.9
CPU的执行时间 = 263.3198113

效果比原博文好一点

epoch=1000,learning_rate=0.009,mini_batch_size=64

在这里插入图片描述

当前是第 0 代,成本值为:1.9711732
当前是第 5 代,成本值为:1.6441493
当前是第 10 代,成本值为:0.9809544
当前是第 15 代,成本值为:0.74599206
...
当前是第 195 代,成本值为:0.005246058
当前是第 200 代,成本值为:0.0045862542
当前是第 205 代,成本值为:0.0041113026
...
当前是第 550 代,成本值为:0.000109061075
当前是第 555 代,成本值为:0.000102569014
当前是第 560 代,成本值为:9.616972e-05
当前是第 565 代,成本值为:9.2503054e-05
...
当前是第 990 代,成本值为:1.489012e-06
当前是第 995 代,成本值为:1.3689555e-06
训练集准确率: 1.0
测试集准确率: 0.875
CPU的执行时间 = 1360.6341113

从图中可以看出,epoch=200之后,cost变化已经不大了

迭代1000次之后,测试集的准确度反而下降了,这说明出现了过拟合的现象。


3.0 相关库代码(tf2修改后)

import math
import numpy as np
import h5py
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.python.framework import ops
def load_dataset():
    train_dataset = h5py.File('datasets/train_signs.h5', "r")
    train_set_x_orig = np.array(train_dataset["train_set_x"][:]) # your train set features
    train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # your train set labels
    test_dataset = h5py.File('datasets/test_signs.h5', "r")
    test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # your test set features
    test_set_y_orig = np.array(test_dataset["test_set_y"][:]) # your test set labels
    classes = np.array(test_dataset["list_classes"][:]) # the list of classes
    train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
    test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))
    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes
def random_mini_batches(X, Y, mini_batch_size = 64, seed = 0):
    """
    Creates a list of random minibatches from (X, Y)
    Arguments:
    X -- input data, of shape (input size, number of examples) (m, Hi, Wi, Ci)
    Y -- true "label" vector (containing 0 if cat, 1 if non-cat), of shape (1, number of examples) (m, n_y)
    mini_batch_size - size of the mini-batches, integer
    seed -- this is only for the purpose of grading, so that you're "random minibatches are the same as ours.
    Returns:
    mini_batches -- list of synchronous (mini_batch_X, mini_batch_Y)
    """
    m = X.shape[0]                  # number of training examples
    mini_batches = []
    np.random.seed(seed)
    # Step 1: Shuffle (X, Y)
    permutation = list(np.random.permutation(m))
    shuffled_X = X[permutation,:,:,:]
    shuffled_Y = Y[permutation,:]
    # Step 2: Partition (shuffled_X, shuffled_Y). Minus the end case.
    num_complete_minibatches = math.floor(m/mini_batch_size) # number of mini batches of size mini_batch_size in your partitionning
    for k in range(0, num_complete_minibatches):
        mini_batch_X = shuffled_X[k * mini_batch_size : k * mini_batch_size + mini_batch_size,:,:,:]
        mini_batch_Y = shuffled_Y[k * mini_batch_size : k * mini_batch_size + mini_batch_size,:]
        mini_batch = (mini_batch_X, mini_batch_Y)
        mini_batches.append(mini_batch)
    # Handling the end case (last mini-batch < mini_batch_size)
    if m % mini_batch_size != 0:
        mini_batch_X = shuffled_X[num_complete_minibatches * mini_batch_size : m,:,:,:]
        mini_batch_Y = shuffled_Y[num_complete_minibatches * mini_batch_size : m,:]
        mini_batch = (mini_batch_X, mini_batch_Y)
        mini_batches.append(mini_batch)
    return mini_batches
def convert_to_one_hot(Y, C):
    Y = np.eye(C)[Y.reshape(-1)].T
    return Y
def forward_propagation_for_predict(X, parameters):
    """
    Implements the forward propagation for the model: LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SOFTMAX
    Arguments:
    X -- input dataset placeholder, of shape (input size, number of examples)
    parameters -- python dictionary containing your parameters "W1", "b1", "W2", "b2", "W3", "b3"
                  the shapes are given in initialize_parameters
    Returns:
    Z3 -- the output of the last LINEAR unit
    """
    # Retrieve the parameters from the dictionary "parameters" 
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']
    W3 = parameters['W3']
    b3 = parameters['b3'] 
                                                           # Numpy Equivalents:
    Z1 = tf.add(tf.matmul(W1, X), b1)                      # Z1 = np.dot(W1, X) + b1
    A1 = tf.nn.relu(Z1)                                    # A1 = relu(Z1)
    Z2 = tf.add(tf.matmul(W2, A1), b2)                     # Z2 = np.dot(W2, a1) + b2
    A2 = tf.nn.relu(Z2)                                    # A2 = relu(Z2)
    Z3 = tf.add(tf.matmul(W3, A2), b3)                     # Z3 = np.dot(W3,Z2) + b3
    return Z3
def predict(X, parameters):
    W1 = tf.convert_to_tensor(parameters["W1"])
    b1 = tf.convert_to_tensor(parameters["b1"])
    W2 = tf.convert_to_tensor(parameters["W2"])
    b2 = tf.convert_to_tensor(parameters["b2"])
    W3 = tf.convert_to_tensor(parameters["W3"])
    b3 = tf.convert_to_tensor(parameters["b3"])
    params = {"W1": W1,
              "b1": b1,
              "W2": W2,
              "b2": b2,
              "W3": W3,
              "b3": b3}

    z3 = forward_propagation_for_predict(X, params)
    prediction = tf.argmax(z3)

    return prediction

其他一些问题

data_format

在tensorflow中,如果不做特殊说明
input矩阵的数据格式都是(样本数N,高度H,宽度W,图像通道数C),即NHWC


在卷积中,tf.conv2d过滤器的数据格式是(过滤器高度f,过滤器宽度f,输入通道数ic(上次层通道数),输出通道数oc(该层过滤器个数))

padding

在tensorflow中,
padding="VALID"表示不使用填充。
padding="SAME"表示使用填充,使得在步长=1时,输出图像的大小=输入图像的大小。即

if data_format starts with "NC", where output_spatial_shape depends on the value of padding.

If padding == "SAME": output_spatial_shape[i] = ceil(input_spatial_shape[i] / strides[i])

If padding == "VALID": output_spatial_shape[i] = ceil((input_spatial_shape[i] - (spatial_filter_shape[i]-1) * dilation_rate[i]) / strides[i]).

tensorflow官方文档 tf.nn.convolution see returns for details

内容概要:本文提出了一种基于改进扩散模型的高海拔地区新能源高波动出力场景生成方法,并提供了完整的Python代码实现。该方法针对高海拔地区风能、光伏等新能源出力波动剧烈、不确定性高的特点,通过优化扩散模型的结构与训练策略,有效捕捉历史数据的概率分布特征与时序相关性,从而生成高质量、多样化的出力场景。文中详细阐述了模型的数学推导、网络架构设计、损失函数优化及采样算法改进,并通过实验证明其在拟合精度、场景多样性与稳定性方面优于传统生成模型,为电力系统在高比例新能源接入下的规划、调度与风险评估提供了可靠的场景输入支持。; 适合人群:具备一定Python编程能力和机器学习基础,从事新能源发电预测、电力系统分析、智能优化、场景生成等方向研究的科研人员、高校研究生及工程技术人员。; 使用场景及目标:①用于高海拔地区风电、光伏出力的不确定性建模与多场景生成;②支撑含高渗透率新能源的电力系统随机优化调度、鲁棒决策与风险评估;③为相关学术研究、论文复现与算法改进提供可运行的技术方案与代码基础; 阅读建议:建议读者结合所提供的完整资源(代码、数据集、说明文档)进行实践操作,重点关注扩散模型的前向加噪与反向去噪过程的设计细节,以及如何将其适配于新能源时序数据的生成任务,通过参数调优与对比实验深入理解模型的生成机制与性能边界。
内容概要:本文围绕基于静态约束法的配电网电动汽车接入容量评估展开研究,提出了一种在新型电力系统背景下评估主动配电网对电动汽车承载能力的方法。研究通过构建数学模型,结合潮流计算与关键约束条件(如电压越限、线路过载等),量化分析配电网可承受的最大电动汽车充电负荷容量,旨在识别规模化电动汽车接入带来的潜在运行风险,并为电网规划与运行提供科学依据。文中配套提供了完整的Matlab代码实现,便于仿真验证与结果复现。此外,该研究与分布式光伏承载力评估、电动汽车可调能力分析等方向形成技术联动,展现了多主题协同的研究体系。; 适合人群:具备电力系统分析基础理论知识及Matlab编程能力的高校研究生、科研机构研究人员,以及从事新能源并网、智能配电网规划与运行等相关领域的工程技术人员。; 使用场景及目标:①用于学术研究中的模型复现与论文撰写支撑;②评估实际配电网中电动汽车大规模接入的可行性与安全边界,指导充电基础设施布局;③作为高校教学案例,帮助学生深入理解电网承载力评估的核心原理、建模方法与仿真技术; 阅读建议:建议结合文中提及的相关研究方向(如二阶锥规划、多面体聚合方法等)进行对比学习,充分利用所提供的Matlab代码与网盘资料开展仿真实验,重点关注约束条件的设定逻辑与潮流计算模块的实现细节,以深化对评估模型机理与工程应用价值的理解。
内容概要:本文围绕“考虑隐私保护的分布式联邦学习电力负荷预测研究”展开,提出了一种基于Python实现的联邦学习框架,旨在解决居民或行业电力负荷预测中用户电表数据隐私泄露的风险。该研究通过构建分布式机器学习模型,使各参与方在不共享原始数据的前提下协同训练全局模型,有效实现了数据“可用不可见”。文中详细阐述了联邦学习的整体架构设计、本地模型训练流程、参数加密传输与安全聚合机制,并结合差分隐私等技术进一步增强系统的隐私保护能力。同时,研究利用真实电力负荷数据集进行了实验验证,展示了方法在预测精度与隐私保障之间的良好平衡,并提供了完整的代码实例与复现指南,便于后续研究与应用拓展。; 适合人群:具备一定机器学习基础和电力系统背景知识,从事智慧能源、隐私计算或人工智能相关方向研究的研究生、科研人员及工程技术人员。; 使用场景及目标:① 实现跨区域、跨主体的电力负荷协同预测,打破数据孤岛;② 在确保用户用电数据隐私安全的前提下提升负荷预测准确性;③ 推动联邦学习在智能电网、需求响应、虚拟电厂等场景中的实际部署与应用。; 阅读建议:建议结合文中提供的Python代码与网盘资料进行动手实践,重点关注联邦学习的通信轮次设计、模型聚合算法(如FedAvg)的实现细节以及差分隐私噪声添加策略,深入理解其对模型性能与隐私强度的影响,为进一步优化与创新奠定基础。
VDA_Band_19.1_3rd edition_2026 English Inspection of Technical Cleanliness 内容概要:本文档为德国汽车工业协会(VDA)发布的第三版《技术清洁度检验:功能相关汽车部件的颗粒污染检测》(VDA 19.1),系统规范了汽车行业中零部件技术清洁度的检测方法与流程。文件涵盖从取样、提取、过滤到分析的全流程标准化操作,重点更新了干法提取(如 Stamp Test 和刷吸法)、小于50µm颗粒的检测、光学子系统和SEM/EDX标准分析方法,并引入统一材料分类体系以提升结果可比性。同时明确了“标准分析”与“自由检验”的区别,前者用于高兼容性检测,后者允许客户与供应商协商定制参数。文档还强化了对非可测组件的技术清洁保障、测量不确定度评估及方法验证的要求,并提供了多个实际案例支持应用落地。; 适合人群:适用于汽车制造业中从事质量控制、工艺开发、供应商管理及相关检测实验室的技术人员和管理人员,尤其适合具备一定质量管理或洁净度检测基础的专业人员。; 使用场景及目标:①用于制定和执行零部件清洁度检测标准;②指导 incoming/outgoing 检验及生产过程监控;③支持失效分析与质量改进项目;④作为企业内部审核和技术交流的依据; 阅读建议:建议结合VDA 19.2及其他相关标准配套使用,重点关注各章节中的起始参数设定、方法选择逻辑及附录中的检查表示例,在实际操作中同步开展方法验证与人员培训,确保检测结果的有效性和可追溯性。
内容概要:本研究聚焦于电动汽车(EV)作为灵活可调资源的能力评估,提出了一种基于多面体聚合与闵可夫斯基和的数学建模方法,用以精确刻画大规模电动汽车集群的可调能力范围。通过将单辆电动汽车的充放电行为抽象为几何空间中的多面体可行域,并利用闵可夫斯基和实现对群体可行域的高效聚合,从而构建出能够反映整体调节潜力的统一数学表达。该方法在Matlab平台上实现了完整的仿真代码,支持对不同场景下电动汽车集群的上、下调能力进行量化评估,为电网调度、需求响应及电力市场机制设计提供了理论依据与工具支撑。; 适合人群:具备电力系统分析、优化理论及Matlab编程基础的研究生、科研人员及从事新能源、智能电网相关工作的工程师。; 使用场景及目标:①用于评估大规模电动汽车接入背景下系统的灵活性资源潜力;②支撑含高比例可再生能源的电力系统调度与规划决策;③为需求响应项目中EV聚合商参与电力市场提供能力申报的技术手段;④作为教学案例帮助理解集合运算在电力系统中的应用。; 阅读建议:学习者应结合Matlab代码深入理解多面体建模与闵可夫斯基和的实现细节,建议从单车模型入手逐步过渡到集群聚合,并尝试调整参数(如数量、SOC分布、功率限制)观察聚合结果的变化,以增强对模型特性的掌握。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值