吴恩达机器学习_可选实验_简单的神经网络

在本次实验中,我们将构建一个简单的神经网络

import numpy as np
import matplotlib.pyplot as plt
plt.style.use('./deeplearning.mplstyle')
import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense
from lab_utils_common import dlc
from lab_coffee_utils import load_coffee_data, plt_roast, plt_prob, plt_layer, plt_network, plt_output_unit
import logging
logging.getLogger("tensorflow").setLevel(logging.ERROR)
tf.autograph.set_verbosity(0)

        数据集

X,Y = load_coffee_data();
print(X.shape, Y.shape)

        让我们在下面绘制咖啡烘焙数据。这两个功能是以摄氏度为单位的温度和以分钟为单位的持续时间。在家烘焙咖啡建议持续时间最好保持在 12 到 15 分钟之间,而温度应在 175 到 260 摄氏度之间。当然,随着温度的升高,持续时间应该会缩短。

plt_roast(X,Y)

        规范化数据

         如果数据被归一化,那么将权重拟合到数据(反向传播,在下周的讲座中将介绍)将更快地进行。这与您在课程 1 中使用的过程相同,其中数据中的每个要素都被归一化为具有相似的范围。以下过程使用 Keras 归一化层。它包含以下步骤:

1.创建一个“归一化层”。请注意,如此处应用的,这不是模型中的层。

2.“适应”数据。这将学习数据集的均值和方差,并在内部保存值。

3.对数据进行规范化。将归一化应用于利用学习模型的任何未来数据非常重要。

print(f"Temperature Max, Min pre normalization: {np.max(X[:,0]):0.2f}, {np.min(X[:,0]):0.2f}")
print(f"Duration    Max, Min pre normalization: {np.max(X[:,1]):0.2f}, {np.min(X[:,1]):0.2f}")
norm_l = tf.keras.layers.Normalization(axis=-1)
norm_l.adapt(X)  # learns mean, variance
Xn = norm_l(X)
print(f"Temperature Max, Min post normalization: {np.max(Xn[:,0]):0.2f}, {np.min(Xn[:,0]):0.2f}")
print(f"Duration    Max, Min post normalization: {np.max(Xn[:,1]):0.2f}, {np.min(Xn[:,1]):0.2f}")

        平铺/复制我们的数据以增加训练集大小并减少训练周期的数量。

Xt = np.tile(Xn,(1000,1))
Yt= np.tile(Y,(1000,1))   
print(Xt.shape, Yt.shape)   

Tensorflow模型

        让我们建立讲座中描述的“咖啡烘焙网络”。有两层具有 sigmoid 激活,如下所示

tf.random.set_seed(1234)  # applied to achieve consistent results
model = Sequential(
    [
        tf.keras.Input(shape=(2,)),
        Dense(3, activation='sigmoid', name = 'layer1'),
        Dense(1, activation='sigmoid', name = 'layer2')
     ]
)

注 1:'tf.keras.Input(shape=(2,)),' 指定了输入的预期形状。这使得 Tensorflow 可以在此时调整权重和偏置参数的大小。 这在探索 Tensorflow 模型时非常有用。在实践中可以省略此语句,当在“model.fit”语句中指定输入数据时,Tensorflow 将调整网络参数的大小。 
注 2:在最后一层包含 sigmoid 激活不被视为最佳实践。相反,它将被计入损失中,从而提高了数值稳定性。这将在后面的实验中更详细地描述。

model.summary()

        摘要中显示的参数计数对应于权重和偏置数组中的元素数,如下所示。

L1_num_params = 2 * 3 + 3   # W1 parameters  + b1 parameters
L2_num_params = 3 * 1 + 1   # W2 parameters  + b2 parameters
print("L1 params = ", L1_num_params, ", L2 params = ", L2_num_params  )


让我们来看看 Tensorflow 实例化的权重和偏差。权重 W应具有大小(输入中的特征数量,层中的单元数量)而偏置大小应与图层中的单元数匹配:

1.在具有 3 个单元的第一层中,我们期望 W 的大小为(2,3)和b应该有 3 个元素。
2.在具有 1 个单位的第二层中,我们期望 W 的大小为(3,1)和b应该有 1 个元素。

W1, b1 = model.get_layer("layer1").get_weights()
W2, b2 = model.get_layer("layer2").get_weights()
print(f"W1{W1.shape}:\n", W1, f"\nb1{b1.shape}:", b1)
print(f"W2{W2.shape}:\n", W2, f"\nb2{b2.shape}:", b2)

以下陈述将在第 2 周中详细描述。目前:

model.compile 语句定义了一个损失函数,并指定了一个编译优化。
model.fit 语句运行梯度下降并将权重拟合到数据。

model.compile(
    loss = tf.keras.losses.BinaryCrossentropy(),
    optimizer = tf.keras.optimizers.Adam(learning_rate=0.01),
)

model.fit(
    Xt,Yt,            
    epochs=10,
)

更新的权重
拟合后,权重已更新:

W1, b1 = model.get_layer("layer1").get_weights()
W2, b2 = model.get_layer("layer2").get_weights()
print("W1:\n", W1, "\nb1:", b1)
print("W2:\n", W2, "\nb2:", b2)

 

接下来,我们将加载一些从上一次训练运行中保存的权重。这样一来,这个笔记本就对 Tensorflow 随时间的变化保持鲁棒性。不同的训练运行可能会产生一些不同的结果,下面的讨论适用于特定的解决方案。随意重新运行此单元格注释掉的笔记本,以查看差异。

W1 = np.array([
    [-8.94,  0.29, 12.89],
    [-0.17, -7.34, 10.79]] )
b1 = np.array([-9.87, -9.28,  1.01])
W2 = np.array([
    [-31.38],
    [-27.86],
    [-32.79]])
b2 = np.array([15.54])
model.get_layer("layer1").set_weights([W1,b1])
model.get_layer("layer2").set_weights([W2,b2])

预测

        一旦你有一个训练好的模型,你就可以用它来进行预测。回想一下,我们模型的输出是一个概率。在这种情况下,良好烤肉的概率。要做出决定,必须将概率应用于阈值。在本例中,我们将使用 0.5

         让我们从创建输入数据开始。该模型需要一个或多个示例,其中示例位于矩阵行中。在本例中,我们有两个特征,因此矩阵将为 (m,2),其中 m 是示例的数量。回想一下,我们已经对输入特征进行了规范化,因此我们也必须对测试数据进行规范化。
若要进行预测,请应用 predict 方法。

X_test = np.array([
    [200,13.9],  # postive example
    [200,17]])   # negative example
X_testn = norm_l(X_test)
predictions = model.predict(X_testn)
print("predictions = \n", predictions)

epoch和batch

        在上面的编译语句中,epoch 的数量设置为 10。这指定了整个数据集应在训练期间应用 10 次。在训练期间,您会看到描述训练进度的输出,如下所示:

epoch1/10
6250/6250 [==============================] - 6s 910us/步 - 损失:0.1782
        第一行 Epoch 1/10 描述模型当前正在运行的纪元。为了提高效率,训练数据集被分解为“批次”。Tensorflow 中批处理的默认大小为 32。我们扩展的数据集中有 200000 个示例或 6250 个批次。第 2 行 6250/6250 [==== 上的符号描述了已执行的批次。

        为了将概率转换为决策,我们应用了一个阈值:

yhat = (predictions >= 0.5).astype(int)
print(f"decisions = \n{yhat}")

        这可以更简洁地完成:

yhat = np.zeros_like(predictions)
for i in range(len(predictions)):
    if predictions[i] >= 0.5:
        yhat[i] = 1
    else:
        yhat[i] = 0
print(f"decisions = \n{yhat}")

 

Layer Functions

        让我们检查一下单元的功能,以确定它们在咖啡烘焙决策中的作用。我们将绘制每个节点的所有输入值(持续时间、温度)的输出。每个单元都是一个逻辑函数,其输出范围可以从 0 到 1。图中的阴影表示输出值 。

注意:在实验室中,我们通常从零开始对事物进行编号,而讲座可能从 1 开始。

plt_layer(X,Y.reshape(-1,),W1,b1,norm_l)

 

        阴影显示每个单元负责不同的“坏烤”区域。当温度过低时,单元 0 的值较大。当持续时间太短时,单元 1 的值较大,而单元 2 的值较大,用于时间/温度的不良组合。值得注意的是,网络通过梯度下降过程自行学习了这些功能。它们与一个人可能选择做出相同决定的功能非常相似。

        最后一层的功能图有点难以可视化。它的输入是第一层的输出。我们知道第一层使用 sigmoid,因此它们的输出范围在 0 到 1 之间。我们可以创建一个 3D 图,用于计算三个输入的所有可能组合的输出。如下所示。在上面,高输出值对应于“不良烘焙”区域。下面,最大输出在区域中,其中三个输入是对应于“良好烘焙”区域的小值。

plt_output_unit(W2,b2)

        最后一张图显示了整个网络的运行情况。
        左图是蓝色阴影表示的最后一层的原始输出。这覆盖在由 X 和 O 表示的训练数据上。
        右图是决策阈值后网络的输出。此处的 X 和 O 对应于网络做出的决策。以下内容需要一些时间才能运行

netf= lambda x : model.predict(norm_l(x))
plt_network(X,Y,netf)

  • 26
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值