在本实验中,我们将使用 Numpy 构建一个小型神经网络。这将是您在 Tensorflow 中实现的同一“咖啡烘焙”网络。
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}")
Numpy Model
还是使用咖啡烘焙这个例子,这里存在两个网络层
如讲座中所述,可以使用 NumPy 构建自己的网络密集层。然后,这可以用来构建多层神经网络。
在第一个可选实验中,您在 NumPy 和 Tensorflow 中构建了一个神经元,并注意到它们的相似性。一层仅包含多个神经元/单元。如讲座中所述,可以利用 for 循环访问层中的每个单元 ('j'),并执行该单位的权重 ('W[:,j]') 的点积,并将该单位的偏差 ('b[j]') 相加以形成 'z'。然后可以将激活函数“g(z)”应用于该结果。让我们在下面尝试构建一个“密集层”子程序。
def my_dense(a_in, W, b, g):
"""
Computes dense layer
Args:
a_in (ndarray (n, )) : Data, 1 example
W (ndarray (n,j)) : Weight matrix, n features per unit, j units
b (ndarray (j, )) : bias vector, j units
g activation function (e.g. sigmoid, relu..)
Returns
a_out (ndarray (j,)) : j units|
"""
units = W.shape[1]
a_out = np.zeros(units)
for j in range(units):
w = W[:,j]
z = np.dot(w, a_in) + b[j]
a_out[j] = g(z)
return(a_out)
以下单元利用上述 my_dense 子程序构建两层神经网络。
def my_sequential(x, W1, b1, W2, b2):
a1 = my_dense(x, W1, b1, sigmoid)
a2 = my_dense(a1, W2, b2, sigmoid)
return(a2)
我们可以在 Tensorflow 中复制来自前一个实验室的经过训练的权重和偏差。
W1_tmp = np.array( [[-8.93, 0.29, 12.9 ], [-0.1, -7.32, 10.81]] )
b1_tmp = np.array( [-9.82, -9.28, 0.96] )
W2_tmp = np.array( [[-31.18], [-27.59], [-32.56]] )
b2_tmp = np.array( [15.41] )
预测
一旦你有了经过训练的模型,你就可以使用它来做出预测。回想一下,我们模型的输出是一个概率。在这种情况下,良好烤肉的概率。要做出决定,必须将概率应用于阈值。在本例中,我们将使用 0.5
让我们从编写一个类似于 Tensorflow 的 model.predict() 的例程开始。这将需要一个矩阵
与所有示例,并通过运行模型进行预测。
def my_predict(X, W1, b1, W2, b2):
m = X.shape[0]
p = np.zeros((m,1))
for i in range(m):
p[i,0] = my_sequential(X[i], W1, b1, W2, b2)
return(p)
我们可以在两个例子中尝试这个例程
X_tst = np.array([
[200,13.9], # postive example
[200,17]]) # negative example
X_tstn = norm_l(X_tst) # remember to normalize
predictions = my_predict(X_tstn, W1_tmp, b1_tmp, W2_tmp, b2_tmp)
为了将概率转换为决策,我们应用了一个阈值:
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}")
这可以更简洁地完成:
yhat = (predictions >= 0.5).astype(int)
print(f"decisions = \n{yhat}")
Network function
此图显示了整个网络的操作,与上一个实验的 Tensorflow 结果相同。左图是蓝色阴影表示的最后一层的原始输出。这覆盖在由 X 和 O 表示的训练数据上。
右图是决策阈值后网络的输出。此处的 X 和 O 对应于网络做出的决策。
netf= lambda x : my_predict(norm_l(x),W1_tmp, b1_tmp, W2_tmp, b2_tmp)
plt_network(X,Y,netf)