今天我们通过分享内容让大家了解一下机器是如何通过学习来识别物体,以及这些物体在机器是怎么看这些物体。今天用单层感知机来模拟机器视图,这里选择数据集中为 10 衣帽图片。这里通过线性方程加上分类激活函数 softmax 完成图片分类任务。这个流程虽然简单,但是通过这个过程我们来了解机器是如何通过梯度下降优化,以减少损失函数为目标不断更新参数来找到一个适合模型(函数);
import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np
from sklearn.metrics import confusion_matrix
from tensorflow import keras
%matplotlib inline
介绍 fashion_mnist 数据集
我们这里使用 fashion_mnist 数据集,一共 70000 张图片其中 60000 张为训练集 10000 张为测试集。图片大小 28 * 28 大小图片
fashion_mnist = keras.datasets.fashion_mnist
(X_train,y_train),(X_test,y_test) = fashion_mnist.load_data()
print(X_train.shape)
print(X_test.shape)
(60000, 28, 28)
(10000, 28, 28)
img_size = 28
img_size_flat = img_size * img_size
img_shape = (img_size,img_size)
num_classes = 10
print(y_train.shape)
print(y_train[0:5])
(60000,)
[9 0 0 3 0]
def plot_images(images,cls,cls_pred=None):
cls_names = ['T-shirt','Trouser','Pullover','Dress','Coat','Sandal','Shirt','Sneaker','Bag','Ankle boot']
fig, axes = plt.subplots(3, 3)
fig.subplots_adjust(hspace=0.3, wspace=0.3)
for i, ax in enumerate(axes.flat):
ax.imshow(imgs[i].reshape(img_shape), cmap='binary')
if cls_pred is None:
xlabel = "True: {0}".format(cls_names[cls_true[i]])
else:
xlabel = "True: {0}, Pred: {1}".format(cls_true[i],cls_pred[i])
ax.set_xlabel(xlabel)
ax.set_xticks([])
ax.set_yticks([])
plt.show()
可视化数据集
通过上面函数读取图片,将数据集中图片显示出来,这样便于大家更加直观观察数据集图,这里有 10 物体,标签标示物体是什么物体
imgs = X_test[0:9]
cls_true = y_test[0:9]
plot_images(imgs,cls_true)
因为我们数据集 y 值为[0,3,5,...,6],需要转换后生成one-hot 编码来参与运算。
# print(a)
# a_one_hot_encode = tf.one_hot(a,num_classes,axis=0)
# print(a_one_hot_encode.shape)
from sklearn.preprocessing import OneHotEncoder
# print(y_test.shape)
# print(y_test)
y_train_cls = y_train
y_test_cls = y_test
y_train = OneHotEncoder(sparse=False).fit_transform(y_train_cls.reshape(-1,1))
y_test = OneHotEncoder(sparse=False).fit_transform(y_test_cls.reshape(-1,1))
print(y_train_cls.shape)
print(y_test_cls.shape)
# help(OneHotEncoder)
X_train = X_train.reshape(-1,784)
X_test = X_test.reshape(-1,784)
print(X_train.shape)
print(y_train.shape)
print(y_train_cls.shape)
print(y_test.shape)
print(y_test_cls.shape)
(60000,)
(10000,)
(60000, 784)
(60000, 10)
(60000,)
(10000, 10)
(10000,)
# 定义 x 占位符作为图片输入,输入 x 形状[None,784]
x = tf.placeholder(tf.float32, [None, img_size_flat],name="x")
# 定义 y_true 为实际值,这里数据集中真实值形状[[0,0,0,1,...,0]]
# 真实值形式为 [None,10]
y_true = tf.placeholder(tf.float32, [None, num_classes],name="y_true")
# 标签这里是由表示类别数据[None] 例如 [1,0,1,9,...,3]
y_true_cls = tf.placeholder(tf.int64, [None],name="y_true_cls")
# 权重 y(None,10) = x (None,784) (784,10) + [10]
weights = tf.Variable(tf.zeros([img_size_flat, num_classes]))
biases = tf.Variable(tf.zeros([num_classes]))
# $$y = x * w + b$$
logits = tf.matmul(x, weights) + biases
y_pred = tf.nn.softmax(logits)
y_pred_cls = tf.argmax(y_pred, axis=1)
# 损失函数使用交叉熵来计算损失函数
cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits,
labels=y_true)
cost = tf.reduce_mean(cross_entropy)
# 定义梯度下降,学习率给 0.5
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.5).minimize(cost)
# 这里推测 softmax 计算出估计概率分布值转为一个值 进行对比
correct_prediction = tf.equal(y_pred_cls, y_true_cls)
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
session = tf.Session()
# 初始化变量
session.run(tf.global_variables_initializer())
batch_size = 100
num_train = len(x_train)
batch_size = 32
idx = np.random.randint(low=0, high=num_train, size=batch_size)
print(idx)
def random_batch(batch_size=32):
idx = np.random.randint(low=0, high=num_train, size=batch_size)
x_batch = X_train[idx]
y_batch = y_train[idx]
y_batch_cls = y_train_cls[idx]
return x_batch, y_batch, y_batch_cls
[32525 10192 5890 2494 36637 42087 4928 52251 22363 50428 22872 45213
26151 4918 18285 8225 20240 24740 48514 17688 8004 51821 30665 36699
33706 40797 39813 11795 36770 56473 9096 46205]
优化
# 优化 num_iterations 是迭代次数
def optimize(num_iterations):
for i in range(num_iterations):
# 获取训练集的一定的样本数,每次取出一定数量样本视为一个批次样本
# x_batch
x_batch, y_true_batch, _ = random_batch(batch_size=batch_size)
# 在 tensorflow 中使用 feed_dict 将输入数据传入到图
#
# 这里没有将 y_true_cls 传入因为这些数据并不参与训练.
feed_dict_train = {x: x_batch,
y_true: y_true_batch}
session.run(optimizer, feed_dict=feed_dict_train)
feed_dict_test = {x: X_test,y_true: y_test,y_true_cls: y_test_cls}
输出精度
def print_accuracy():
# 计算 accuracy.
acc = session.run(accuracy, feed_dict=feed_dict_test)
# 输出 accuracy.
print("Accuracy on test-set: {0:.1%}".format(acc))
输出混淆矩阵
def print_confusion_matrix():
cls_true = y_test_cls
cls_pred = session.run(y_pred_cls, feed_dict=feed_dict_test)
cm = confusion_matrix(y_true=cls_true,
y_pred=cls_pred)
print(cm)
plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
plt.tight_layout()
plt.colorbar()
tick_marks = np.arange(num_classes)
plt.xticks(tick_marks, range(num_classes))
plt.yticks(tick_marks, range(num_classes))
plt.xlabel('Predicted')
plt.ylabel('True')
plt.show()
输出错误
def plot_example_errors():
correct, cls_pred = session.run([correct_prediction, y_pred_cls],
feed_dict=feed_dict_test)
incorrect = (correct == False)
images = X_test[incorrect]
cls_pred = cls_pred[incorrect]
cls_true = y_test_cls[incorrect]
plot_images(images=images[0:9],
cls=cls_true[0:9],
cls_pred=cls_pred[0:9])
通过显示权重,我们可以了解到机器到底学到什么,机器是怎么认识
def plot_weights():
# 获取权重 w 的值
# 784 * 10 矩阵,10 维度对应 10 个类别,
w = session.run(weights)
# 要做这件事,我们需要先找到权重的最小值和最大值。
w_min = np.min(w)
w_max = np.max(w)
fig, axes = plt.subplots(3, 4)
fig.subplots_adjust(hspace=0.3, wspace=0.3)
for i, ax in enumerate(axes.flat):
# 只显示 10 权重图
if i<10:
image = w[:, i].reshape(img_shape)
ax.set_xlabel("Weights: {0}".format(i))
ax.imshow(image, vmin=w_min, vmax=w_max, cmap='seismic')
ax.set_xticks([])
ax.set_yticks([])
# Ensure the plot is shown correctly with multiple plots
# in a single Notebook cell.
plt.show()
print_accuracy()
Accuracy on test-set: 10.0%
plot_example_errors()
optimize(num_iterations=1)
print_accuracy()
Accuracy on test-set: 19.8%
plot_example_errors()
plot_weights()
在张图,机器把鞋学的不错,机器可以清晰认出coat 和 鞋子
optimize(num_iterations=9)
print_accuracy()
Accuracy on test-set: 54.5%
plot_example_errors()
plot_weights()
optimize(num_iterations=50)
训练到 50 发现机器表现还不错 76.8 别忘了这里只有一层神经网的,可以认为感知机。
print_accuracy()
Accuracy on test-set: 76.8%
plot_example_errors()
plot_weights()
过拟合
当训练次数增加学习成绩反而下降
optimize(num_iterations=990)
print_accuracy()
Accuracy on test-set: 68.3%
plot_example_errors()
plot_weights()
最后希望大家关注我们微信公众号