梅飞飞飞的假期学习日记DAY4

今天和同学聚了一下,但是不能拉下学习进度,继续看第三章

本来要在昨天发了,太晚了有点麻了就没继续往后看了

使用Tensorflow中的GradientTape API,我们能够实现对一个输入张量进行一些计算,然后就可以检索计算结果相对于输入的梯度。

1-1 使用GradientTape

input_var = tf.Variable(initial_value=3.)
with tf.GradientTape() as tape:
    result = tf.square(input_var)
gradient = tape.gradient(result, input_var)

如果要监视常数张量,我们必须对其调用tape.watch(),手动将其标记为被监视的张量

1-2 对常数张量输入使用GradientTape

input_const = tf.constant(3.)
with tf.GradientTape() as tape:
    tape.watch(input_const)
    result = tf.square(input_const)
gradient = tape.gradient(result, input_const)

1-3 利用GradinetTape实现求解二阶梯度

time = tf.Variable(0.)
with tf.GradientTape() as outer_tape:
    with tf.GradientTape() as outer_tape:
        position = 4.9 * time ** 2  // 相当于二分之一重力加速度乘时间的平方
    speed = inner_tape.gradient(position, time)
acceleration = outer_tape.gradient(speed, time)

相当于一个求一阶导一个求二阶导

用Tensorflow编写线性分类器

2-1 首先我们需要在二维平面上随机生成两个类别的点

num_samples_per_class = 1000
negative_samples = np.random.multivariate_normal(
    mean=[0,3],
    cov=[[1, 0.5],[0.5, 1]],
    size=num_samples_per_class)
// 生成一千个随机点

positive_samples = np.random.multivariate_normal(
    mean=[3,0],
    cov=[[1, 0.5],[0.5, 1]],
    size=num_samples_per_class)

//两个点阵的协方差相同,均值不同

2-2 接着我们将两个类别堆叠成一个形状为(2000,2)的数组

inputs = np.vstack((negative_samples, positive_samples)).astype(np.float32)

2-3 生成目标标签 

targets = np.vstack((np.zeros((num_samples_per_class, 1), dtype="float32"),
                    np.ones((num_samples_per_class, 1), dtype="float32")))

2-4 绘制两个点类的图像

import matplotlib.pyplot as plt
plt.scatter(inputs[:, 0], inputs[:, 1], c = targets[:,0])
plt.show()

构建好了这两个类别的点集后,我们接下来就要通过创建一个线性分类器来学习划分这两个类别。

prediction = w * input + b 通过对模型进行训练,更新参数值,由此来使得预测值与目标值之差的平方最小化

2-5 创建线性分类器的变量

input_dim = 2
output_dim = 1
W = tf.Variable(initial_value=tf.random.uniform(shape=(input_dim, output_dim)))
b = tf.Variable(initial_value=tf.zeros(shape=(output_dim,)))

2-6 前向传播函数

def  model(inputs):
    return tf.matmul(inputs, W) + b

此处我们案例中的点集都只有x,y两个坐标,输入都是二维输入,所以W权重包含W1,W2。而b则是一个标量系数。所以我们的结果计算式应该是:

prediction = [ [w1], [w2] ] * [x, y] + b = w1 * x + w2 * y + b

 

2-7 均方误差损失函数

def square_loss(targets, predictions):
    per_sample_losses = tf.square(targets - predictions)
    return tf.reduce_mean(per_sample_losses)

per_sample_losses和targets、predictions变量的形状相同,所以在最后我们利用reduce_mean将损失值转换为了标量损失值

2-8 训练步骤函数

learning_rate = 0.1

def training_step(inputs, targets):
    with tf.GradientTape() as tape:
        predictions = model(inputs)
        loss = square_loss(targets, predictions)
    grad_loss_wrt_W, grad_loss_wrt_b = tape.gradient(loss, [W, b])
    W.assign_sub(grad_loss_wrt_W * learning_rate)
    b.assign_sub(grad_loss_wrt_b * learning_rate)
    return loss

在梯度带作用域内进行前向传播,随后便可在外通过调用gradient来获取当前损失值相对于不同参数的梯度值,并在随后通过梯度和学习率更新参数值

2-9 批量训练循环

for step in range(40):
    loss = training_step(inputs, targets)
    print(f"Loss at step {step}: {loss:.4f}")

在训练几轮发现损失值稳定在某个值时,我们就可以绘制一下根据predictions得到的结果分布图

2-10 绘图

predictions = model(inputs)
plt.scatter(inputs[:,0], inputs[:, 1], c=predictions[:, 0] > 0.5)
plt.show()

如果属于第一类的概率大于0.5就归类为类别1,此时c=1;同理在另外一种情况归类为类别0

最后我们可以得到类别0和类别1在此处的数学定义

类别0:w1*x+w2*y+b<0.5     类别2: w1*x+w2*y+b > 0.5

那么我们便发现这其实是一条二维平面上的直线,我们要做的就是找到这条直线完成在直线两侧的分类

2-11 绘制直线

x = np.linespace(-1,4,100)
t = -W[0] / W[1] * x + (0.5 - b) / W[1]
plt.plot(x,y, "-r")
plt.scatter(inputs[:,0], inputs[:,1], c=predictions[;, 0] > 0.5)

由此绘制出了一条红色直线,并将预测结果的散点图绘制在了图中

通过这个案例进一步促进了我对分类器的工作原理了解

你可能感兴趣的:(学习,python,深度学习)