TensorFlow Tutorial-2

版权为吴恩达老师所有,参考Koala_Tree的博客,部分根据自己实践添加

使用google翻译,部分手工翻译

你可能需要的参考资料https://pan.baidu.com/s/1VCkeolXINRYuWt7XnXU_JQ

2 - 在tensorflow中构建您的第一个神经网络

在这部分任务中,您将使用tensorflow构建神经网络。请记住,实现张量流模型有两个部分:

  • 创建计算图
  • 运行图表

让我们深入研究您想要解决的问题!

2.0 - 问题陈述:SIGNS数据集

一天下午,我和一些朋友决定教我们的电脑破译手语。我们花了几个小时在白墙前拍照,想出了以下数据集。现在,您的工作是构建一种算法,以促进从语言障碍者到不懂手语的人的通信。

  • 训练集:1080个图像(64乘64像素)的符号表示从0到5的数字(每个数字180个图像)。
  • 测试集:120张图片(64乘64像素)的符号,表示从0到5的数字(每个数字20张图片)。

请注意,这是SIGNS数据集的子集。完整的数据集包含更多符号。

以下是每个数字的示例,以及如何解释我们如何表示标签。在我们将图像重新降低到64 x 64像素之前,这些是原始图片。

还在路上,稍等...

                                   图1:SIGNS数据集

然后运行以下代码以加载数据集。

X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = load_dataset()

更改下面的索引并运行单元格以显示数据集中的一些示例。

index=0
plt.imshow(X_train_orig[index])
plt.show()
print("y = "+str(np.squeeze(Y_train_orig[:,index])))

像往常一样,您展平图像数据集,然后将其除以255进行标准化。最重要的是,您将每个标签转换为one hot矢量,如图1所示。运行下面的单元格来执行此操作。

X_train_flatten=X_train_orig.reshape(X_train_orig.shape[0],-1).T 
X_test_flatten=X_test_orig.reshape(X_test_orig.shape[0],-1).T 

X_train=X_train_flatten/255.0
X_test=X_test_flatten/255.0

Y_train=convert_to_one_hot(Y_train_orig,6)
Y_test=convert_to_one_hot(Y_test_orig,6)

print ("number of training examples = " + str(X_train.shape[1]))
print ("number of test examples = " + str(X_test.shape[1]))
print ("X_train shape: " + str(X_train.shape))
print ("Y_train shape: " + str(Y_train.shape))
print ("X_test shape: " + str(X_test.shape))
print ("Y_test shape: " + str(Y_test.shape))

请注意,12288来自64×64×364×64×3。每个图像是正方形,64乘64像素,3是RGB颜色。在继续之前,请确保所有这些形状对您有意义。

您的目标是构建一种能够高精度识别符号的算法。为此,您将构建一个张量流模型,该模型与您之前在numpy中为cat识别构建的模型几乎相同(但现在使用softmax输出)。这是一个很好的机会,可以将你的numpy实现与tensorflow实现进行比较。

该模型LINEAR - > RELU - > LINEAR - > RELU - > LINEAR - > SOFTMAX。SIGMOID输出层已转换为SOFTMAX。当有两个以上的类时,SOFTMAX层是SIGMOID的推广。

2.1 - 创建占位符

您的第一个任务是为X和创建占位符Y。这将允许您稍后在运行会话时传递您的训练数据。

练习:实现以下函数以在tensorflow中创建占位符。

def create_placeholders(n_x,n_y):
    X=tf.placeholder(tf.float32,shape=[n_x,None])
    Y=tf.placeholder(tf.float32,shape=[n_y,None])

    return X,Y

X, Y = create_placeholders(12288, 6)
print ("X = " + str(X))
print ("Y = " + str(Y))

2.2 - 初始化参数

您的第二个任务是初始化张量流中的参数。

练习:实现以下函数初始化张量流中的参数。您将使用Xavier Initialization进行权重和零偏置初始化。形状如下。例如,为了帮助您,对于W1和b1,您可以使用:

W1 = tf.get_variable("W1", [25,12288], initializer = tf.contrib.layers.xavier_initializer(seed = 1))
b1 = tf.get_variable("b1", [25,1], initializer = tf.zeros_initializer())

请使用seed = 1以确保您的结果符合我们的要求。

def initialize_parameters():
    tf.set_random_seed(1)

    W1=tf.get_variable("W1",[25,12288],initializer=tf.contrib.layers.xavier_initializer(seed=1))
    b1=tf.get_variable("b1",[25,1],initializer=tf.zeros_initializer())
    W2=tf.get_variable("W2",[12,25],initializer=tf.contrib.layers.xavier_initializer(seed=1))
    b2=tf.get_variable("b2",[12,1],initializer=tf.zeros_initializer())
    W3=tf.get_variable("W3",[6,12],initializer=tf.contrib.layers.xavier_initializer(seed=1))
    b3=tf.get_variable("b3",[6,1],initializer=tf.zeros_initializer())

    parameters={"W1":W1,
    "b1":b1,
    "W2":W2,
    "b2":b2,
    "W3":W3,
    "b3":b3,
    }

    return parameters
tf.reset_default_graph()
with tf.Session() as sess:
    parameters = initialize_parameters()
    print("W1 = " + str(parameters["W1"]))
    print("b1 = " + str(parameters["b1"]))
    print("W2 = " + str(parameters["W2"]))
    print("b2 = " + str(parameters["b2"]))
tips:
1.可能非常慢

正如所料,尚未评估参数。

2.3 - tensorflow中的前向传播

您现在将在tensorflow中实现前向传播模块。该函数将接收参数字典,它将完成正向传递。您将使用的功能是:

  • tf.add(...,...) 做一个补充
  • tf.matmul(...,...) 进行矩阵乘法
  • tf.nn.relu(...) 应用ReLU激活

问题:实现神经网络的正向传递。我们为您评估了numpy等价物,以便您可以将tensorflow实现与numpy进行比较。重要的是要注意前向传播停止在z3。原因在于,在tensorflow中,最后的线性层输出被给出作为计算损失的函数的输入。因此,你不需要a3

def forward_propagation(X,parameters):
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']
    W3 = parameters['W3']
    b3 = parameters['b3']

    Z1=tf.add(tf.matmul(W1,X),b1)
    A1=tf.nn.relu(Z1)
    Z2=tf.add(tf.matmul(W2,A1),b2)
    A2=tf.nn.relu(Z2)
    Z3=tf.add(tf.matmul(W3,A2),b3)

    return Z3
tf.reset_default_graph()

with tf.Session() as sess:
    X, Y = create_placeholders(12288, 6)
    parameters = initialize_parameters()
    Z3 = forward_propagation(X, parameters)
    print("Z3 = " + str(Z3))

您可能已经注意到前向传播不会输出任何缓存。当我们进行向后传播时,在下面你会明白为什么。

2.4计算成本

如前所述,使用以下方法计算成本非常容易:

tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits = ..., labels = ...))

问题:执行以下成本函数。 
- 重要的是要知道预期的“ logits”和“ labels”输入tf.nn.softmax_cross_entropy_with_logits是形状的(例子数,num_classes)。因此,我们为您转换了Z3和Y. 
- 此外,tf.reduce_mean基本上是对例子的总结。

def compute_cost(Z3,Y):
    logits=tf.transpose(Z3)
    labels=tf.transpose(Y)

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

    return cost
tf.reset_default_graph()

with tf.Session() as sess:
    X, Y = create_placeholders(12288, 6)
    parameters = initialize_parameters()
    Z3 = forward_propagation(X, parameters)
    cost = compute_cost(Z3, Y)
    print("cost = " + str(cost))

2.5 - 向后传播和参数更新

这是您对编程框架感激不尽的地方。所有的反向传播和参数更新都在一行代码中处理。将该线合并到模型中非常容易。

计算成本函数后。您将创建一个“ optimizer”对象。运行tf.session时,必须将此对象与成本一起调用。调用时,它将使用所选方法和学习速率对给定成本执行优化。

例如,对于梯度下降,优化器将是:

optimizer = tf.train.GradientDescentOptimizer(learning_rate = learning_rate).minimize(cost)

要进行优化,您需要:

_ , c = sess.run([optimizer, cost], feed_dict={X: minibatch_X, Y: minibatch_Y})

这通过以相反的顺序通过张量流图来计算反向传播。从成本到输入。

注意编码时,我们经常使用_“一次性”变量来存储我们以后不需要使用的值。这里,_采用optimizer我们不需要的评估值(并c获取cost变量的值)。

2.6 - 构建模型

现在,你将把它们全部结合在一起!

练习:实施模型。您将调用之前实现的功能。

def model(X_train,Y_train,X_test,Y_test,learning_rate=0.0001,num_epochs=1500,minibatch_size=32,print_cost=True):
    ops.reset_default_graph()
    tf.set_random_seed(1)
    seed=3
    (n_x,m)=X_train.shape
    n_y=Y_train.shape[0]
    costs=[]

    X,Y=create_placeholders(n_x,n_y)

    parameters=initialize_parameters()

    Z3=forward_propagation(X,parameters)

    cost=compute_cost(Z3,Y)

    optimizer=tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

    init=tf.global_variables_initializer()

    with tf.Session() as sess:
        sess.run(init)

        for epoch in range(num_epochs):
            epoch_cost=0
            num_minibatches=int(m/minibatch_size)
            seed=seed+1
            minibatches=random_mini_batches(X_train,Y_train,minibatch_size,seed)

            for minibatch in minibatches:
                (minibatch_X,minibatch_Y)=minibatch
                _,minibatch_cost=sess.run([optimizer,cost],feed_dict={X:minibatch_X,Y:minibatch_Y})
                epoch_cost+=minibatch_cost/num_minibatches

        if print_cost and epoch%100==0 :
            print("Cost after epoch %i: %f" %(epoch,epoch_cost))
        if print_cost and epoch%10==0 :
            costs.append(epoch_cost)

    plt.close()
    plt.plot(np.squeeze(costs))
    plt.ylabel("cost")
    plt.xlabel("iterations (per tens)")
    plt.title("Learning rate = "+str(learning_rate))
    plt.show()

    parameters=sess.run(parameters)
    print("Parameters have been trained!")

    correct_prediction=tf.equal(tf.argmax(Z3),tf.argmax(Y))
    accuracy=tf.reduce_mean(tf.case(correct_prediction,"float"))
    print("Train Accuracy:",accuracy.eval({X:X_train,Y:Y_train}))
    print("Test Accuracy:",accuracy.eval({X:X_test,Y:Y_test}))

    return parameters

运行以下代码来训练您的模型!在我们的机器上大约需要5分钟。你的“Cost after epoch 100”应该是1.016458。如果不是,不要浪费时间; 中断训练,并尝试更正您的代码。如果是正确的费用,请休息一下,然后在5分钟后回来!

parameters = model(X_train, Y_train, X_test, Y_test)

还在路上,稍等...

令人惊讶的是,您的算法可以识别表示0到5之间的数字的符号,准确率为71.7%。

见解
- 您的模型似乎足以适应训练集。但是,考虑到训练和测试精度之间的差异,您可以尝试添加L2或dropout正则化以减少过度拟合。 
- 将会话视为训练模型的代码块。每次在mini-batch上运行会话时,它都会训练参数。总共运行会话很多次(1500个世代),直到你获得训练有素的参数。

2.7 - 使用您自己的图像进行测试(可选/未评分的练习)

恭喜你完成了这项任务。您现在可以拍摄手的图片并查看模型的输出。

import scipy
from PIL import Image
from scipy import ndimage

my_image = "thumbs_up.jpg"

fname = "images/" + my_image
image = np.array(ndimage.imread(fname, flatten=False))
my_image = scipy.misc.imresize(image, size=(64,64)).reshape((1, 64*64*3)).T
my_image_prediction = predict(my_image, parameters)

plt.imshow(image)
print("Your algorithm predicts: y = " + str(np.squeeze(my_image_prediction)))

确实应该得到一个“竖起大拇指”,虽然你可以看到算法似乎错误地将其分类。原因是训练集不包含任何“竖起大拇指”,因此模型不知道如何处理它!我们称之为“不匹配的数据分布”,它是“构建机器学习项目”下一门课程的各种课程之一。

你应该记住的
- Tensorflow是深度学习中使用的编程框架
-
tensorflow中的两个主要对象类是Tensors和运算符。 
- 当您在tensorflow中编码时,您必须执行以下步骤:
- 创建包含
Tensors(变量,占位符...)和操作(tf.matmul,tf.add,...)的图形
- 创建会话
- 初始化会话
- 运行执行图形的会话
- 您可以像在模型()中看到的那样多次执行图形- 
在“优化器”对象上运行会话时自动完成反向传播和优化。

猜你喜欢

转载自blog.csdn.net/smoggyxhdz/article/details/82290364