TensorFlow2 Fashion-MNIST图像分类(一)

2023-10-30

1.数据集介绍

FashionMNIST 是一个替代 MNIST 手写数字集的图像数据集。 它是由 Zalando(一家德国的时尚科技公司)旗下的研究部门提供。其涵盖了来自 10 种类别的共 7 万个不同商品的正面图片。
FashionMNIST 的大小、格式和训练集/测试集划分与原始的 MNIST 完全一致。60000/10000 的训练测试数据划分,28x28的灰度图片。你可以直接用它来测试你的机器学习和深度学习算法性能,且不需要改动任何的代码。
官方的关于数据集的介绍可以参考:

https://github.com/zalandoresearch/fashion-mnist

标注编号 类别说明
0 T-shirt/top(T恤)
1 Trouser(裤子)
2 Pullover(套衫)
3 Dress(裙子)
4 Coat(外套)
5 Sandal(凉鞋)
6 Shirt(汗衫)
7 Sneaker(运动鞋)
8 Bag(包)
9 Ankle boot(踝靴)

2.模型训练

Tensorflow版本:2.2.0

2.1 数据加载

数据的加载使用可以直接调用tensorflow包进行联网加载,也可以将数据下载到本地,进行本地数据读取。

代码如下:

#首先导入需要的包,并查看版本信息
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import sklearn
import pandas as pd
import os
import sys
import time
import gzip
import tensorflow as tf

from tensorflow import keras

print(tf.__version__)
print(sys.version_info)
for module in mpl, np, pd, sklearn, tf, keras:
    print(module.__name__, module.__version__)
    
# 联网数据加载使用
fashion_mnist = keras.datasets.fashion_mnist
(x_train_all, y_train_all), (x_test, y_test) = fashion_mnist.load_data()

本地数据下载之后,包含四个文件:
在这里插入图片描述

然后,将原来的加载函数load_data稍作修改,即可加载本地文件,只需要将远程下载地址,更改为你的本地文件所在目录即可,此处我的文件目录为data。

def load_data():
  """Loads the Fashion-MNIST dataset.

  This is a dataset of 60,000 28x28 grayscale images of 10 fashion categories,
  along with a test set of 10,000 images. This dataset can be used as
  a drop-in replacement for MNIST. The class labels are:

  | Label | Description |
  |:-----:|-------------|
  |   0   | T-shirt/top |
  |   1   | Trouser     |
  |   2   | Pullover    |
  |   3   | Dress       |
  |   4   | Coat        |
  |   5   | Sandal      |
  |   6   | Shirt       |
  |   7   | Sneaker     |
  |   8   | Bag         |
  |   9   | Ankle boot  |

  Returns:
      Tuple of Numpy arrays: `(x_train, y_train), (x_test, y_test)`.

      **x_train, x_test**: uint8 arrays of grayscale image data with shape
        (num_samples, 28, 28).

      **y_train, y_test**: uint8 arrays of labels (integers in range 0-9)
        with shape (num_samples,).

  License:
      The copyright for Fashion-MNIST is held by Zalando SE.
      Fashion-MNIST is licensed under the [MIT license](
      https://github.com/zalandoresearch/fashion-mnist/blob/master/LICENSE).

  """
  dirname = os.path.join('datasets', 'fashion-mnist')
  # 数据下载到本地,提供一个本地的文件夹地址
  base = 'data/'
  # base = 'https://storage.googleapis.com/tensorflow/tf-keras-datasets/'
  files = [
      'train-labels-idx1-ubyte.gz', 'train-images-idx3-ubyte.gz',
      't10k-labels-idx1-ubyte.gz', 't10k-images-idx3-ubyte.gz'
  ]

  paths = [base + f_name for f_name in files]
  # for fname in files:
  #   paths.append(get_file(fname, origin=base + fname, cache_subdir=dirname))

  with gzip.open(paths[0], 'rb') as lbpath:
    y_train = np.frombuffer(lbpath.read(), np.uint8, offset=8)

  with gzip.open(paths[1], 'rb') as imgpath:
    x_train = np.frombuffer(
        imgpath.read(), np.uint8, offset=16).reshape(len(y_train), 28, 28)

  with gzip.open(paths[2], 'rb') as lbpath:
    y_test = np.frombuffer(lbpath.read(), np.uint8, offset=8)

  with gzip.open(paths[3], 'rb') as imgpath:
    x_test = np.frombuffer(
        imgpath.read(), np.uint8, offset=16).reshape(len(y_test), 28, 28)

  return (x_train, y_train), (x_test, y_test)

# 本地数据读取
(x_train_all, y_train_all), (x_test, y_test) = load_data()

2.2 数据划分

提供的数据包含60000/10000 的训练/测试数据。我们再将训练集进行划分,train和valid,原有的测试数据用于模型最终的测试,训练集前5000数据作为valid,剩余的数据作为train集合。

# 原有训练数据划分为train和valid
x_valid, x_train = x_train_all[:5000], x_train_all[5000:]
y_valid, y_train = y_train_all[:5000], y_train_all[5000:]

print(x_valid.shape, y_valid.shape)
print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)

数据集合划分情况如下:

(5000, 28, 28) (5000,)

(55000, 28, 28) (55000,)

(10000, 28, 28) (10000,)

对其中的一个样本进行可视化查看

def show_single_image(img_dir):
    plt.imshow(img_dir, cmap="binary")
    plt.show()

show_single_image(x_train[0])

绘图结果如下:

在这里插入图片描述

我们可以多查看一些数据样本,编写函数进行自定义查看。

def show_imgs(n_rows, n_cols, x_data, y_data, class_names):
    """
    指定行列个数,显示数据集中的n_rows*n_cols个样本图像
    """
    assert len(x_data) == len(y_data)
    assert n_rows * n_cols < len(x_data)
    plt.figure(figsize = (n_cols * 1.4, n_rows * 1.6))
    for row in range(n_rows):
        for col in range(n_cols):
            index = n_cols * row + col
            plt.subplot(n_rows, n_cols, index + 1)
            plt.imshow(x_data[index], cmap="binary", interpolation = "nearest")
            plt.axis('off')
            plt.title(class_names[y_data[index]])
    plt.show()

# 指定类别
class_names = ['T-shirt', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
# 查看15个样本图片
show_imgs(3, 5, x_train, y_train, class_names)

次数我们查看15个样本图片,结果如下:
多张图片查看

2.3 模型构建

我们使用tensorflow2中集成的kera包进行Sequential模型构建:keras.models.Sequential()
Sequential提供了非常简便的方式进行神经网络模型的构建,就是将要添加的模型一层一层的逐层进行add即可,也可以通过列表的方式,一起进行添加。

model = keras.models.Sequential()
model.add(keras.layers.Flatten(input_shape=[28, 28]))
model.add(keras.layers.Dense(300, activation="relu"))
model.add(keras.layers.Dense(100, activation="relu"))
model.add(keras.layers.Dense(10, activation="softmax"))

# 模型组合成列表进行统一添加
"""
model = keras.models.Sequential([
    keras.layers.Flatten(input_shape=[28, 28]),
    keras.layers.Dense(300, activation='relu'),
    keras.layers.Dense(100, activation='relu'),
    keras.layers.Dense(10, activation='softmax')
])
"""

# 关于激活函数的解释
# relu: y = max(0, x)
# softmax: 将向量变成概率分布. x = [x1, x2, x3], 
#          y = [e^x1/sum, e^x2/sum, e^x3/sum], sum = e^x1 + e^x2 + e^x3

# reason for sparse: y->index. y->one_hot->[] 
# 由于此处的数据类型y是一个数,所以此处使用sparse_categorical_crossentropy,如果y是one_hot向量,那么此处使用categorical_crossentropy
#模型编译
model.compile(loss="sparse_categorical_crossentropy",
              optimizer = "sgd",
              metrics = ["accuracy"])

经过上面的步骤,模型已经构建完成,编译生成模型结构,接下来可以查看模型的相关信息。

# 查看模型的各层
model.layers
#输出结果
[<tensorflow.python.keras.layers.core.Flatten at 0x7f4e6d11b438>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f4e6d11beb8>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f4e6d11b588>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f4e6d90bfd0>]
# 模型的结构信息,包括参数情况
model.summary()

# 输出结果
Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten_2 (Flatten)          (None, 784)               0         
_________________________________________________________________
dense_6 (Dense)              (None, 300)               235500    
_________________________________________________________________
dense_7 (Dense)              (None, 100)               30100     
_________________________________________________________________
dense_8 (Dense)              (None, 10)                1010      
=================================================================
Total params: 266,610
Trainable params: 266,610
Non-trainable params: 0
_________________________________________________________________

关于各层模型的向量的维度计算,解释如下:

[None, 784] * W + b -> [None, 300] W.shape [784, 300], b = [300]

输入的数据就是[None,2828],然后经过Flatten之后,就是[None, 784],接着就是添加全连接层,维度是300,那么这个时候XW + b = y,可以算出W的维度,也就是权重的维度应该是[784, 300],偏置的维度也就是[300]。对于后边全连接层的各参数的维度计算同样的道理可以得出。

接下来就是模型训练,使用的是fit函数。
这里指定了epochs的个数,就是一共要训练多少次,训练一次就是将x_train数据跑一遍模型。而每一次往模型中输入多少个样本,就是batch_size,此处指定了64,batch_size越大,占用的内存越大,所以要参照自己的机器配置适当设置。

history = model.fit(x_train, y_train, epochs=10,validation_split=False,batch_size=64,validation_data=(x_valid, y_valid))

模型训练过程如下:

Epoch 1/10
860/860 [==============================] - 3s 3ms/step - loss: 2.3026 - accuracy: 0.0986 - val_loss: 2.3028 - val_accuracy: 0.0914
Epoch 2/10
860/860 [==============================] - 3s 3ms/step - loss: 2.3026 - accuracy: 0.0991 - val_loss: 2.3029 - val_accuracy: 0.0914
Epoch 3/10
860/860 [==============================] - 3s 3ms/step - loss: 2.3026 - accuracy: 0.0985 - val_loss: 2.3028 - val_accuracy: 0.0914
Epoch 4/10
860/860 [==============================] - 3s 3ms/step - loss: 2.3026 - accuracy: 0.0988 - val_loss: 2.3029 - val_accuracy: 0.0914
Epoch 5/10
860/860 [==============================] - 3s 3ms/step - loss: 2.3026 - accuracy: 0.1001 - val_loss: 2.3028 - val_accuracy: 0.0914
Epoch 6/10
860/860 [==============================] - 3s 3ms/step - loss: 2.3026 - accuracy: 0.0986 - val_loss: 2.3028 - val_accuracy: 0.0914
Epoch 7/10
860/860 [==============================] - 3s 3ms/step - loss: 2.3026 - accuracy: 0.1008 - val_loss: 2.3028 - val_accuracy: 0.0914
Epoch 8/10
860/860 [==============================] - 3s 3ms/step - loss: 2.3026 - accuracy: 0.0984 - val_loss: 2.3028 - val_accuracy: 0.0914
Epoch 9/10
860/860 [==============================] - 3s 3ms/step - loss: 2.3026 - accuracy: 0.0973 - val_loss: 2.3028 - val_accuracy: 0.0914
Epoch 10/10
860/860 [==============================] - 3s 3ms/step - loss: 2.3026 - accuracy: 0.1003 - val_loss: 2.3028 - val_accuracy: 0.0914

可以看出由于设置的batch_size为64,所以训练一次要进行860个批次的样本输入。

针对history,可以查看他的相关类型和相关信息:

# 查看类型
type(history)
# 模型结果相关信息
history.history
# 输出结果如下:
{'accuracy': [0.09905454516410828,
  0.10116363316774368,
  0.09749090671539307,
  0.09958181530237198,
  0.09843636304140091,
  0.09821818023920059,
  0.09734545648097992,
  0.1000545471906662,
  0.09998181462287903,
  0.0989818200469017],
 'loss': [2.302921772003174,
  2.302874803543091,
  2.302971839904785,
  2.3028604984283447,
  2.3029799461364746,
  2.3029377460479736,
  2.3030099868774414,
  2.302891731262207,
  2.3029096126556396,
  2.3028926849365234],
 'val_accuracy': [0.09860000014305115,
  0.09759999811649323,
  0.10019999742507935,
  0.09139999747276306,
  0.09799999743700027,
  0.1111999973654747,
  0.09799999743700027,
  0.10019999742507935,
  0.10019999742507935,
  0.10080000013113022],
 'val_loss': [2.302537679672241,
  2.3035120964050293,
  2.303284168243408,
  2.303611993789673,
  2.3037195205688477,
  2.30253267288208,
  2.3035061359405518,
  2.30228328704834,
  2.302734851837158,
  2.3030896186828613]}

最后对模型返回结果中的相关参数画图显示变化情况。

def plot_learning_curves(history):
    pd.DataFrame(history.history).plot(figsize=(8, 5))
    plt.grid(True)
    plt.gca().set_ylim(0, 1)
    plt.show()

plot_learning_curves(history)

结果如下图:
在这里插入图片描述

从最终的结果可以看出,准确率很低,而且从整个训练过程也可以看出,每次训练完之后,基本上没有太大的变化。

我们对数据集中的数据的大小进行统计查看:

print(np.max(x_train), np.min(x_train))
# 输出结果:
255 0

图像灰度值从0到255,数据存在较大的分布跨度。输入数据的维度是28*28,其展开之后就是784。在机器学习领域中,不同评价指标(即特征向量中的不同特征就是所述的不同评价指标)往往具有不同的量纲和量纲单位,这样的情况会影响到数据分析的结果,为了消除指标之间的量纲影响,需要进行数据标准化处理,以解决数据指标之间的可比性。原始数据经过数据标准化处理后,各指标处于同一数量级,适合进行综合对比评价。其中,最典型的就是数据的归一化处理。简而言之,归一化的目的就是使得预处理的数据被限定在一定的范围内(比如[0,1]或者[-1,1]),从而消除奇异样本数据导致的不良影响

归一化的目的,有三个方面可以参考:

  • 避免具有不同物理意义和量纲的输入变量不能平等使用;
  • bp中常采用sigmoid函数作为转移函数,归一化能够防止净输入绝对值过大引起的神经元输出饱和现象;
  • 保证输出数据中数值小的不被吞食.
    所以,从上面的训练过程和结果可以看出,我们的模型并没有很好地拟合,所以,需要解决输入数据的归一化问题,下个部分进行归一化的模型构建。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TensorFlow2 Fashion-MNIST图像分类(一) 的相关文章

随机推荐

  • docker alpine镜像中遇到 not found

    1 问题 docker alpine镜像中遇到 sh xxx not found 例如 monerod 注 此可执行文件已放到 usr local bin sh monerod not found 2 原因 由于alpine镜像使用的是mu
  • Tomcat的简单使用

    目录 1 Tomcat 是什么 2 下载安装 3 启动Tomcat 4 部署静态页面 4 1 部署单个 HTML 4 2 部署 HTML 到单独的目录中 5 tomcat 运行和 直接 html 运行区别 1 Tomcat 是什么 Tomc
  • CppCheck代码静态检测工具

    文章目录 一 简述 二 安装 二 使用 2 1 第一个测试程序 2 2 检查文件夹中所有文件 2 3 检查部分或过滤部分文件 三 严重性 四 其他常用用法 4 1 启用其他检查 4 2 保存结果到文件 4 3 多线程检查 4 3 设置目标平
  • laravel 发布资源失败

    Unable to locate publishable resources Publishing complete php artisan vendor publish 列出所有后选择数字发布
  • Spring Boot Maven项目使用SystemPath引用第三方平台遇到的大坑

    本次与算法厂家对接 使用了他们的Jar包 最先考虑的是不使用Maven仓库 便于离线开发 首先采用了方案
  • 推荐系统介绍

    课程内容 推荐系统在电子商务领域得到普遍的运用 推荐系统本质上是销售系统的一部分 在便利店 推荐系统是导购牌 类目货架 是老板娘 在超市 推荐系统是导购牌 类目货架 是销售员 在电商 推荐系统是什么 不管是在便利店 还是超市 或者电商网站
  • 【数学建模美赛】2023数模美赛备赛指南

    二月中旬要开始美赛了 应该是准备考研这一年的唯一一次正规比赛了 希望能好好完成 在博客边分享边准备 打算开一个新坑 好好准备一下 文章目录 报名事项 赛题特点 六道赛题特点 A B C D E F 竞赛攻略 报名事项 官方网站 美赛官网 h
  • 群晖docker安装chrome

    在docker中下载oldiy chrome novnc 启动这个映像 安装完成后 启动容器 如果路由器wan口是公网ip 可以在路由器上添加5900和8083的端口映射 会更方便访问 如果没有那就可以用群晖的quickconnect 假如
  • 利用Docker 搭建 upload-labs 靶场

    Docker 搭建 upload labs 靶场 靶场搭建 获取upload labs镜像 docker search upload labs 然后下载镜像 命令 docker pull c0ny1 upload labs 如下图即为下载成
  • 样式设置 /deep/

    样式设置scoped属性带来的问题 通常我们在写样式的时候会在style标签中加上scoped属性 相信这个属性的作用大家都很清楚 Scoped CSS规范是Web组件产生不污染其他组件 也不被其他组件污染的CSS规范 但是这样有时候也会遇
  • Python爬虫从入门到精通:(34)大文件下载_Python涛哥

    还记得我们之前爬取的校花网图片吗 课程地址 爬取校花网中的图片数据 这节课我们利用scrapy的大文件下载 来下载校花网图片 http www 521609 com daxuexiaohua 创建工程 我们先来创建一个工程imgPro 创建
  • 机器学习笔记十二:分类与回归树CART

    更新时间 2017 11 18 简化语言 更加通俗 实现 实现部分采用的数据集是机器学习实战中的数据集 代码则是按照自己的理解重新改写了一遍 读取数据模块 data py import numpy as np def loadData fi
  • JAVA中如何写注释

    文章目录 0 写在前面 1 格式 2 演示 2 1 单行注释 2 2 多行注释 2 3 生成文档注释 3 写在最后 0 写在前面 一段良好的代码应该有注释 这样可以使不同的创作者或者阅读者进行良好的阅读 与大多数程序设计语言一样 Java
  • 统信桌面操作系统产线总经理王耀华:深度开源社区的十五年运营路

    深度 deepin 社区是以桌面操作系统为主的开源社区 已经持续运营15年 有接近13万的注册用户 全球下载超过8000万 海外超过300万 并基于deepin衍生出ubuntuDDE manjaro deepin等多个发行版本 2022
  • 错题本 - 机器学习

    下面关于支持向量机 SVM 的描述错误的是 A 是一种监督式学习的方法 B 可用于多分类的问题 C 是一种生成式模型 D 支持非线性的核函数 答案 C 解析 SVM是判别式模型 SVM 支持向量机 SVM 是一类按监督学习方式对数据进行二元
  • File,FileInputStream,FileReader,InputStreamReader,BufferReader 的区别使用

    File 类介绍 File 类封装了对用户机器的文件系统进行操作的功能 例如 可以用 File 类获得文件上次修改的时间 移动 或者对文件进行删除 重命名 换句话说 流类关注的是文件内容 而 File 类关注的是文件在磁盘上的存储 主要方法
  • 使用jsp获取页面的访问ip地址并统计访问量

    jsp获取页面的访问ip地址并统计访问量 考虑到ip地址是唯一不重复的 可以使用set集合来放置ip 然后用set size 得到ip的数量 话不多说 代码在下面
  • 毕业项目SSM框架配置文件之web.xml

  • 【AIGC】AI-Agents最新成果-斯坦福AI小镇源码解读

    写在前面的话 今年年初斯坦福和谷歌的研究人员创建了一个类似于 模拟人生 的微型 RPG 虚拟世界 其中 25 个角色由 GPT 和自定义代码控制 并在arxiv上提交了论文版本 引起了对AIGC 游戏的广泛讨论 8月 该项目在GitHub上
  • TensorFlow2 Fashion-MNIST图像分类(一)

    1 数据集介绍 FashionMNIST 是一个替代 MNIST 手写数字集的图像数据集 它是由 Zalando 一家德国的时尚科技公司 旗下的研究部门提供 其涵盖了来自 10 种类别的共 7 万个不同商品的正面图片 FashionMNIS