【AI达人特训营】服装分类:Fashion-MNIST数据集


该项目基于飞桨构建模型对Fashion-MNIST数据集分类。数据集含60000张训练图、10000张测试图,为28x28灰度图,分10类。项目先解压数据、查看概览,再划分训练集与验证集(8:2),计算均值和方差,定义数据读取器。构建简单卷积神经网络,经两次训练(固定和变动学习率),评估得精度0.91225,最后保存模型并实现预测功能。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

【AI达人特训营】服装分类:Fashion-MNIST数据集

一、简要介绍

  • 图像分类(image classification)是计算机视觉领域中最简单最基础的任务,学习研究图像分类是每个计算机视觉研究者的必经之路,图像分类网络也是很多更复杂任务(如目标检测、语义分割等)算法的基础。
  • 项目目标:构建一种机器学习算法模型,对Fashion-MNIST数据集正确分类
  • 环境要求:飞桨 PaddlePaddle 2.2 及以上版本
  • Fashion-MNIST由60000张训练集图像、10000张测试集图像及对应的标签构成,每张图像是分辨率为28x28的灰度图像,包含10种分类:T恤、裤子、套头衫、连衣裙、大衣、凉鞋、衬衫、运动鞋、包、短靴。
  • 数据特点:图片太小,但数量充足,标签分布均匀
  • 项目概述:
  • 主要思路:数据图片是灰度图形式,数量充足,但是28 * 28 的尺寸是比较小的,因此考虑对原始数据进行放大处理,以使特征充分暴露。也可考虑其他数据增强方式,比如制作jia的RGB三通道图像等。
  • 操作过程:分析数据--》划分数据集--》构建数据读取器--》构建网络模型--》训练模型--》评估模型--》保存模型--》调用模型进行预测
  • 模型问题:本项目手动构建了一个简单模型,结构比较简单、原始,但好处是规模较小,容易训练,效果也还可以吧。另外这个小模型还有个好处,就是你可以很方便的对结构进行变更,来比较不同的模型配置的实际效果。针对本项目,层数越多未必越好,卷积核太大效果也不太理想。
  • 训练问题:本项目进行了两次训练,第一次使用固定学习率,第二次使用了变动学习率,以进一步提升精度。训练中要特别注意曲线变化,因为模型很小,很容易过拟合。
  • 一个瑕疵:使用 interpolation=cv2.INTER_CUBIC 方式放大图片的效果比默认方式好,但有个副作用:每次放大生成的图片可能略有不同,导致均值和方差的计算结果不是定值,喂给模型的图片也会存在细微差别,虽然人眼看不出来。但从实际的训练效果来看,似乎影响不大。
  • 一个坑:图片分类模型的输出层通常接一个softmax,虽然这并不会对精度提升有帮助,但是会使输出的结果比较规矩。但是需要注意:使用 paddle.nn.CrossEntropyLoss 做损失函数时,如果模型中已经有了sofmax输出层,则应该设置 use_softmax = False,否则会导致训练失败,loss值不下降。

二、环境设置

  • 这个示例使用 paddle version:2.3.0
  • 使用pandas处理csv文件
  • 使用cv2对图片进行放大
In [ ]
# import 导入模块import paddlefrom paddle.io import Dataset#from paddle.vision.transforms import functional as F#from paddle.vision.transforms import RandomRotation#from paddle.vision import transforms#import matplotlibimport matplotlib.pyplot as plt#import PIL.Image as Imageimport numpy as npimport pandas as pdimport cv2import osimport shutilimport zipfile#import platform#import globimport random#import datetime#---打印paddle 版本print(f"paddle version:{paddle.__version__}")
   

三、数据概览

  • 数据集链接:https://aistudio.baidu.com/aistudio/datasetdetail/145250
  • 数据以csv文件方式提供
  • 解压并查看数据
In [2]
# func 解压zip文件def unzip_files(file_path,unzip_path):
    zipFile = zipfile.ZipFile(file_path)    try:        for file in zipFile.namelist():
            zipFile.extract(file, unzip_path)    except:        pass
    finally:
        zipFile.close()# 定义这个解压函数不是必须的,仅仅是为了跨系统时代码可以通用。也可以手动解压,Linux 可以使用unzip等工具
    In [3]
# run 解压训练数据# 28*28灰度图,10种分类:T恤、裤子、套头衫、连衣裙、大衣、凉鞋、衬衫、运动鞋、包、短靴fd_data = "./data/"    # data文件夹#zip_file_path = "./data/fashion-mnist_train.zip"    # 训练数据zip_file_path = "./data/data145250/fashion-mnist_train.zip"    # 训练数据 aistudio数据挂载路径unzip_files(os.path.normpath(zip_file_path),os.path.normpath(fd_data))    # 解压训练数据# 压缩包里面有两个文件,“fashion-mnist_train.csv”是训练数据,“fashion-mnist_test_data.csv”是测试数据
    In [ ]
# run 查看原始数据train_csv_path = "./data/fashion-mnist_train.csv"train_csv = pd.read_csv(os.path.normpath(train_csv_path))print(train_csv)# fashion-mnist_train.csv 这个文件中,第一列是标签,后面是灰度图每一个像素点对应的灰度值,运行这段代码可以看到基本文件结构
    In [5]
# run 对标签数量进行统计train_csv["label"].value_counts()# 这个统计是为了查看数据的分布情况。这个数据集的分布非常均匀,每一个标签的图片数量都是6000
       
9    6000
8    6000
7    6000
6    6000
5    6000
4    6000
3    6000
2    6000
1    6000
0    6000
Name: label, dtype: int64
                In [6]
# func 传入索引,提取图片img_e_h, img_e_w = 96, 96    # 放大尺寸def get_pic(row_idx, data_csv, enlarge=False):
    img_data = list(data_csv.loc[row_idx])    # 获取一行数据
    img_label = img_data[0]    # 获取标签
    img = img_data[1:]    # 获取数据
    img = np.array(img,dtype="uint8")    # 转换为np数组
    img.resize(img_h,img_w)    # 还原成28*28
    if(enlarge):    # 放大图片
        img = cv2.resize(img, (img_e_h, img_e_w), interpolation=cv2.INTER_CUBIC)    # interpolation=cv2.INTER_CUBIC效果好但速度慢,而且每次放大的结果都稍有不同
        #img = cv2.resize(img, (img_e_h, img_e_w))    # 使用默认放大方式,执行此行
    return (img_label, img)# 这个函数用于从csv文件中提取还原出图片# 函数中有一个放大操作,这里是放大到96*96,这个时候人眼已经可以比较轻松的识别了# 原始图片非常小,不好操作,所以考虑进行放大处理# 没有放大到整数倍,是因为担心放大到整数倍对于计算机来说没有多大意义# 也可以放到很大,但是模型参数会比较多,96*96相对比较适中# fashion-mnist_train.csv 文件中的第一列是标签,fashion-mnist_test_data.csv 文件中的第一列是索引,所以训练和测试可以共用这个函数
    In [7]
# run 随机查看一张图片img_h, img_w = 28, 28   # 图片高度和宽度label_list = ["T恤","裤子","套头衫","连衣裙","大衣","凉鞋","衬衫","运动鞋","包","短靴"]    # 标签列表row_count = train_csv.shape[0]    # 获取行数 60000row_idx = random.randint(0 ,row_count - 1)    # 随机生成一个行索引label1, img1 = get_pic(row_idx, train_csv)print(f"Label for a random pic:{label_list[label1]}")
plt.imshow(img1,cmap="gray")    # 显示灰度图# 尝试还原一张图片,看看原始图片的样子# 这段代码同时初始化了标签列表
       
Label for a random pic:连衣裙
       
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/cbook/__init__.py:2349: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
  if isinstance(obj, collections.Iterator):
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/cbook/__init__.py:2366: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
  return list(data) if isinstance(data, collections.MappingView) else data
       
               
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/image.py:425: DeprecationWarning: np.asscalar(a) is deprecated since NumPy v1.16, use a.item() instead
  a_min = np.asscalar(a_min.astype(scaled_dtype))
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/image.py:426: DeprecationWarning: np.asscalar(a) is deprecated since NumPy v1.16, use a.item() instead
  a_max = np.asscalar(a_max.astype(scaled_dtype))
       
                In [8]
# run 尝试将图片放大label1, img1 = get_pic(row_idx, train_csv, enlarge=True)print(f"Label for a random pic:{label_list[label1]}")
plt.figure(figsize=(8,8),dpi=50)    #修改显示的图像大小#plt.axis('off')plt.imshow(img1,cmap="gray")print(np.array(img1).shape)# 尝试将图片放大,看看放大后的效果
       
Label for a random pic:连衣裙
(96, 96)
       
               

四、数据集准备

  • 分割训练集和验证集
  • 训练集和验证集比例:8:2
  • 计算均值和方差
  • 定义了两个计算均值和标准差的函数,实际使用的是第二个
  • 放大图片使用了interpolation=cv2.INTER_CUBIC,这个放大方法得到的图片并不总是一定的,这导致对均值和标准差的计算结果存在不确定性
  • 定义数据读取器
  • interpolation=cv2.INTER_CUBIC放大方法的问题,使得:即使是同一张图片,每次喂给模型的数据会存在非常细微的不同
  • 准备训练集和验证集
In [9]
# run 划分 训练集和验证集idx_split = int(row_count*0.8)    # 前80%设置为训练集print(idx_split)    # 48000# 原始数据集已经是乱序排列,所以没有在进行乱序处理,直接计算出一个分割值
       
48000
        In [10]
# func 计算原始图片的均值和标准差def calc_means_stdevs():
    means, stdevs = 0, 0   # 均值和标准差
    pix_count = img_h*img_w*row_count    # 像素总数
    sum = train_csv.iloc[:,1:].sum(axis=1)    # 对所有行的第1列到最末列求和
    sum = np.array(sum)    # 转成np数组
    sum = sum.sum()    # 求和
    means = sum / pix_count    # 均值
    print(f"means:{means}")

    data_all = train_csv.iloc[:,1:]    # 获取所有数据
    data_all = np.array(data_all)    # 转成np数组
    data_all = data_all - means    # 减去均值
    data_all = data_all**2    # 平方
    stdevs = np.sqrt(data_all.sum() / pix_count)   # 得到标准差
    print(f"stdevs:{stdevs}")    return (means, stdevs)# 这个函数不是必须的,因为我这里是使用放大后的图片,仅列示出来以供参考
    In [11]
# func 计算放大后图片的均值和标准差def calc_means_stdevs_enlarge():
    means, stdevs = 0, 0   # 均值和标准差
    pix_count = img_e_h*img_e_w*row_count    # 像素总数
    sum = 0    # 求和
    for idx in range(0, row_count):
        label1, img1 = get_pic(row_idx, train_csv, enlarge=True)    # 获取放大后的图片
        img1 = np.array(img1)    # 转成np数组
        sum += img1.sum()    # 计算和

    means = sum / pix_count    # 均值
    print(f"means:{means}")

    sum1 = 0    # 减均值,然后求平方和
    for idx in range(0, row_count):
        label1, img1 = get_pic(row_idx, train_csv, enlarge=True)    # 获取放大后的图片
        img1 = np.array(img1)    # 转成np数组
        img1 = img1 - means    # 减均值
        img1 = img1 ** 2    # 平方
        sum1 += img1.sum()    # 计算和

    stdevs = np.sqrt(sum1 / pix_count)   # 得到标准差
    print(f"stdevs:{stdevs}")    return (means, stdevs)# 这个函数用来计算放大后的图片的均值和标准差,因为我们要把放大后的图片喂给模型# 由于放大方式使用了interpolation=cv2.INTER_CUBIC,这个方法的放大结果存在一定不确定性,导致均值和标准差的计算结果也存在一定不确定性# 使用 interpolation=cv2.INTER_CUBIC是我这个示例的瑕疵之一,但从实际效果来看,似乎影响甚微
    In [23]
# run 计算均值和标准差#means, stdevs = 0, 1    # 不使用减均值除标准差的处理,执行此行#means, stdevs = calc_means_stdevs()    # 要使用原始数据的均值和方差,执行此行means, stdevs = calc_means_stdevs_enlarge()    # 要使用放大后图片的均值和方差,执行此行
       
means:61.16547309027778
stdevs:54.048929187014885
        In [24]
# class 定义数据读取器class DataReader(Dataset):
    def __init__(self,
                means,    #均值
                stdevs,    #标准差
                data_csv,    # 数据
                mode='train_set'):    # train_set val_set
        """
        初始化函数
        """
        self.mode = mode
        self.data = []
        self.data_csv = data_csv
        self.means = means
        self.stdevs = stdevs

        idx_begin = 0
        idx_end = idx_split    # 分割点
        
        if mode == 'train_set':            pass
        elif mode == "val_set":
            idx_begin = idx_split
            idx_end = row_count    # 总条数
        
        for idx in range(idx_begin, idx_end):
            d_row = list(train_csv.loc[idx])    # 取出一行
            d_label = d_row[0]    # 分离出标签
            #d_date = d_row[1:]    # 分离出数据
            self.data.append([idx, d_label])        print(f"size of {mode}:{len(self.data)}")                      
    def __getitem__(self, index):
        """
        读取图片,对图片进行归一化处理,返回图片和 标签
        """
        row_idx, label = self.data[index]  # 获取数据
        label, img = get_pic(row_idx, train_csv, enlarge=True)    # 获取图片,并放大
        
        img = np.array(img, dtype="float32")    # 转换为np数组,float32格式
        
        img = img - self.means    # 减均值
        img = img / self.stdevs    # 除方差
        img = img / 255    # 归一化
        img = np.expand_dims(img, axis=0)    #扩展一个维度

        return img, np.array(label, dtype='int64')    def __len__(self):
        """
        获取样本总数
        """
        return len(self.data)# 喂给模型的是处理好的数据,处理方法要在这里定义好
    In [ ]
# run 准备数据集读取器train_dataset = DataReader(means, stdevs, train_csv, 'train_set')    # 训练集数据加载器val_dataset = DataReader(means, stdevs, train_csv, 'val_set')    # 评估集数据加载器idx_max = train_dataset.__len__()
idx = random.randint(0 ,idx_max - 1)    # 随机生成一个索引data, label = train_dataset[idx]    # 随机取出一个数据print(f"data label:{label}")print(f"data shape:{np.array(data).shape}")print(f"data content:\n{data}")
   

五、模型组网

  • 定义网络模型
  • 自定义了一个简单模型
  • 准备模型网络

模型结构图

       

In [26]
# class 构造模型class FashionNet(paddle.nn.Layer):    # 自定义的类
    def __init__(self, num_classes=10, model_name="model_mk0"):    # 输出的分类数,模型名称
        super(FashionNet, self).__init__()
        self.model_name = model_name

        self.conv1 = paddle.nn.Conv2D(in_channels=1, out_channels=96, kernel_size=(5, 5), stride=1, padding = 1)        #self.pool1 = paddle.nn.MaxPool2D(kernel_size=2, stride=2)
        self.relu1=paddle.nn.ReLU()
        
        self.conv2 = paddle.nn.Conv2D(in_channels=96, out_channels=96, kernel_size=(3,3),  stride=2, padding = 0)        #self.pool2 = paddle.nn.MaxPool2D(kernel_size=2, stride=2)
        self.relu2=paddle.nn.ReLU()
        
        self.conv3 = paddle.nn.Conv2D(in_channels=96, out_channels=96, kernel_size=(3,3), stride=2, padding = 0)
        self.relu3=paddle.nn.ReLU()
        
        self.conv4 = paddle.nn.Conv2D(in_channels=96, out_channels=96, kernel_size=(3,3), stride=2, padding = 1)        #self.pool4 = paddle.nn.MaxPool2D(kernel_size=2, stride=2)
        self.relu4=paddle.nn.ReLU()        #self.conv5 = paddle.nn.Conv2D(in_channels=96, out_channels=96, kernel_size=(5,5), stride=1, padding = 1)
        #self.pool5 = paddle.nn.MaxPool2D(kernel_size=2, stride=2)
        #self.relu5=paddle.nn.ReLU()

        self.flatten = paddle.nn.Flatten()        
        #self.linear1 = paddle.nn.Linear(in_features=14336, out_features=224)
        self.linear1 = paddle.nn.Linear(in_features=11616, out_features=96)
        self.relu6=paddle.nn.ReLU()
        self.linear2 = paddle.nn.Linear(in_features=96, out_features=num_classes)

        self.sm1 = paddle.nn.Softmax()        
    def forward(self, x):
        x = self.conv1(x)        #x = self.pool1(x)
        x = self.relu1(x)
        
        x = self.conv2(x)
        x = self.relu2(x)
        
        x = self.conv3(x)
        x = self.relu3(x)
        
        x = self.conv4(x)        #x = self.pool4(x)
        x = self.relu4(x)        #x = self.conv5(x)
        #x = self.relu5(x)

        x = self.flatten(x)
        
        x = self.linear1(x)
        x = self.relu6(x)
        x = self.linear2(x)

        x = self.sm1(x)        
        return x
    In [27]
# run 准备网络model = paddle.Model(FashionNet(num_classes=10,model_name="fashion_mk1"))print(f"model name:{model.network.model_name}")
model.summary((1, 1, 96, 96))
       
model name:fashion_mk1
---------------------------------------------------------------------------
 Layer (type)       Input Shape          Output Shape         Param #    
===========================================================================
   Conv2D-9       [[1, 1, 96, 96]]     [1, 96, 94, 94]         2,496     
    ReLU-6       [[1, 96, 94, 94]]     [1, 96, 94, 94]           0       
   Conv2D-10     [[1, 96, 94, 94]]     [1, 96, 46, 46]        83,040     
    ReLU-7       [[1, 96, 46, 46]]     [1, 96, 46, 46]           0       
   Conv2D-11     [[1, 96, 46, 46]]     [1, 96, 22, 22]        83,040     
    ReLU-8       [[1, 96, 22, 22]]     [1, 96, 22, 22]           0       
   Conv2D-12     [[1, 96, 22, 22]]     [1, 96, 11, 11]        83,040     
    ReLU-9       [[1, 96, 11, 11]]     [1, 96, 11, 11]           0       
   Flatten-3     [[1, 96, 11, 11]]        [1, 11616]             0       
   Linear-5         [[1, 11616]]           [1, 96]           1,115,232   
    ReLU-10          [[1, 96]]             [1, 96]               0       
   Linear-6          [[1, 96]]             [1, 10]              970      
   Softmax-3         [[1, 10]]             [1, 10]               0       
===========================================================================
Total params: 1,367,818
Trainable params: 1,367,818
Non-trainable params: 0
---------------------------------------------------------------------------
Input size (MB): 0.04
Forward/backward pass size (MB): 17.02
Params size (MB): 5.22
Estimated Total Size (MB): 22.27
---------------------------------------------------------------------------
       
{'total_params': 1367818, 'trainable_params': 1367818}
               

六、模型训练

  • 配置参数,加载数据,训练模型
  • 模型中已经使用了softmax做输出层,在使用CrossEntropyLoss时不需要使用softmax做归一化,需要配置use_softmax = False
  • 模型训练了两次,第一次使用固定学习率,第二次使用变动学习率
In [ ]
# run 训练模型 固定学习率fd_visualdl_log = "visualdl_log"    # visualdl log文件夹lr = 5e-5    # 学习率 0.00005optim = paddle.optimizer.Adam(learning_rate=lr, parameters=model.parameters())    # 优化器visualdl = paddle.callbacks.VisualDL(log_dir=fd_visualdl_log)   # VisualDL工具的回调函数model.prepare(optim, 
              paddle.nn.CrossEntropyLoss(use_softmax = False),     # 因为模型中已经使用了softmax做输出层,因此这里面不需要使用softmax做归一化
              paddle.metric.Accuracy())    # 验证函数model.fit(train_dataset,    # 训练数据集
            val_dataset,    # 评估数据集
            epochs=7,    # 训练的总轮次
            batch_size=5,    # 训练使用的批大小,使用变动学习率时,batch_size最好小一些,6,8
            verbose=1,    # 设置可视化
            callbacks=[visualdl])    # visualdl# 第一次训练,先使用固定学习率看看效果
   

第一阶段训练曲线

       

In [ ]
# run 训练模型 变动学习率fd_visualdl_log = "visualdl_log"    # visualdl log文件夹lr = 5e-5    # 学习率scheduler = paddle.optimizer.lr.LinearWarmup(
                    learning_rate=lr, warmup_steps=20, start_lr=5e-5, end_lr=3e-4, verbose=False)
optim = paddle.optimizer.Adam(learning_rate=scheduler, parameters=model.parameters())
visualdl = paddle.callbacks.VisualDL(log_dir=fd_visualdl_log)   # VisualDL工具的回调函数model.prepare(optim, 
              paddle.nn.CrossEntropyLoss(use_softmax = False),     # 因为模型中已经使用了softmax做输出层,因此这里面不需要使用softmax做归一化
              paddle.metric.Accuracy())    # 验证函数model.fit(train_dataset,    # 训练数据集
            val_dataset,    # 评估数据集
            epochs=7,    # 训练的总轮次
            batch_size=5,    # 训练使用的批大小,使用变动学习率时,batch_size最好小一些,6,8
            verbose=1,    # 设置可视化
            callbacks=[visualdl])    # visualdl# 第二次训练,这次加了个wormup,看看是不是能提升一下精度
   

第二阶段训练曲线

       

七、模型评估

  • 评估模型训练效果
In [30]
# run 评估模型result = model.evaluate(val_dataset, verbose=1)print(result)# 由于模型结构非常简单原始,这大概是这个模型能达到的最好效果了
       
Eval begin...
step 12000/12000 [==============================] - loss: -0.0000e+00 - acc: 0.9123 - 5ms/step          
Eval samples: 12000
{'loss': [-0.0], 'acc': 0.91225}
       

八、保存模型

  • 保存训练的结果
In [31]
# func 保存模型参数的函数fd_model_save = "./model_save/"    #模型保存目录os.path.normpath(fd_model_save)def model_save(model):
    if os.path.exists(os.path.normpath(fd_model_save)):shutil.rmtree(os.path.normpath(fd_model_save))    #保存模型的文件夹
    print(f"saving model {model.network.model_name} for training...")
    model.save(fd_model_save+model.network.model_name)  # save for training
    print(f"saving model {model.network.model_name} for inference...")
    model.save(fd_model_save+model.network.model_name, False)  # save for inference
    print(f"model {model.network.model_name} has been saved to {fd_model_save}")# 这个函数用来 把训练好的模型保存起来,以用于日后调用或者再次训练
    In [32]
# run 保存模型model_save(model)
       
saving model fashion_mk1 for training...
saving model fashion_mk1 for inference...
model fashion_mk1 has been saved to ./model_save/
       

九、模型预测

  • 用训练的模型进行预测
  • 随机选取一个test集中的数据进行预测
In [33]
# run 解压test数据集fd_data = "./data/"    # data文件夹#zip_file_path = "./data/fashion-mnist_test_data.zip"    # test数据zip_file_path = "./data/data145250/fashion-mnist_test_data.zip"    # test数据 aistudio数据挂载路径unzip_files(os.path.normpath(zip_file_path),os.path.normpath(fd_data))    # 解压test数据# 把test数据集解压出来,这里复用了解压函数,也可以手动解压
    In [ ]
# run 查看test原始数据test_csv_path = "./data/fashion-mnist_test_data.csv"test_csv = pd.read_csv(os.path.normpath(test_csv_path))print(test_csv)# test数据和训练数据的唯一却别是,第一列不是标签而是索引值,这样就可以复用前面定义的图片提取并放大的函数
    In [35]
# run 查看一张随机 test集图片row_count = test_csv.shape[0]    # 获取行数 60000row_idx = random.randint(0 ,row_count - 1)    # 随机生成一个行索引idx1, img1 = get_pic(row_idx, test_csv)

plt.imshow(img1,cmap="gray")    # 显示灰度图# 随机查看一张test图片,先人眼判断一下
       
               
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/image.py:425: DeprecationWarning: np.asscalar(a) is deprecated since NumPy v1.16, use a.item() instead
  a_min = np.asscalar(a_min.astype(scaled_dtype))
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/image.py:426: DeprecationWarning: np.asscalar(a) is deprecated since NumPy v1.16, use a.item() instead
  a_max = np.asscalar(a_max.astype(scaled_dtype))
       
                In [36]
# func 模型预测函数,传入模型类、模型名称、图片索引、数据集dataframe,加载模型并预测数据def model_predict(my_net,model_name,img_idx,data_csv):
    #paddle.set_device('gpu:1')
    #paddle.set_device('cpu')
    #定制化模型(无需label)
    input_define = paddle.static.InputSpec(shape=[1,3,112,112], dtype="float32", name="img")
    model = paddle.Model(my_net(num_classes=10,model_name=model_name),input_define)    #加载模型参数
    model_path = os.path.join(os.path.normpath(fd_model_save), model_name)
    model.load(model_path)
    model.prepare()

    idx, img = get_pic(row_idx, data_csv, enlarge=True)    # 获取图片,并放大
    img = np.array(img, dtype="float32")    # 转换为np数组,float32格式 
    img = img - means    # 减均值
    img = img / stdevs    # 除方差
    img = img / 255    # 归一化
    img = np.expand_dims(img, axis=0)    # 扩展一个维度
    img = np.expand_dims(img, axis=0)    # 扩展一个维度
    #img = paddle.to_tensor(img)

    result = model.predict(test_data=[img])    #print(result)
    #idx = np.argmax(result)
    #print(f"result:[{label_list[idx]}]")
    return result# 这个函数用来调用已经保存的模型,然后对传入的数据进行预测
    In [37]
# run 用模型预测选取的图片,并打印输出预测结果result = model_predict(FashionNet,"fashion_mk1",idx1,test_csv)print(result)
idx = np.argmax(result)print(f"result:[{label_list[idx]}]")# 把刚才随机选出的图片交给模型进行预测,看看预测的结果
       
Predict begin...
step 1/1 [==============================] - 4ms/step
Predict samples: 1
[(array([[5.2177566e-13, 3.2803663e-15, 1.3896773e-05, 1.4886105e-16,
        9.9998593e-01, 3.0198786e-18, 2.2157795e-07, 9.9112047e-19,
        1.9151252e-12, 2.9413131e-20]], dtype=float32),)]
result:[大衣]
       

十、总结

针对本项目:

  • 使用 interpolation=cv2.INTER_CUBIC 方式放大图片的效果比默认方式好,但有个副作用:每次放大生成的图片可能略有不同,导致均值和方差的计算结果不是定值
  • 大卷积核未必效果好
  • 图片放大到 96 * 96 比放大到 112 * 112 或 224 * 224 更划算
  • 学习率,5e-5比3e-4 效果好
  • 使用变动的学习率,效果往往更好
  • 层数多未必好用
  • 使用 paddle.nn.CrossEntropyLoss 做损失函数时,如果模型中已经有了sofmax输出层,则应该设置 use_softmax = False
In [ ]
# run 清理文件if os.path.exists("visualdl_log"):shutil.rmtree("visualdl_log")    #visualdl_log文件夹if os.path.exists(os.path.normpath(fd_model_save)):shutil.rmtree(os.path.normpath(fd_model_save))    #保存模型的文件夹# 如果数据有用,可不必清理# 但是在测试过程中,应该保持一个良好的习惯
    代码解释 In [ ]
# 查看可视化曲线 :(本地运行时)终端运行  visualdl --logdir ./visualdl_log


# https  # 两次  # 转成  # 加载  # 不需要  # 有个  # 使用了  # 大到  # 大后  # 标准差  # 均值  # 图片放大  # linux  # paddlepaddle  # 算法  # pandas  # igs  # red  # 排列  # csv文件  # ai  # 工具  # python 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化91478 】 【 技术知识72672 】 【 云计算0 】 【 GEO优化84317 】 【 优选文章0 】 【 营销推广36048 】 【 网络运营41350 】 【 案例网站102563 】 【 AI智能45237


相关推荐: LALAL.AI教程:音视频人声分离、降噪终极指南  3步教你用AI自动分类文件,整理电脑告别杂乱  使用双端队列(deque)解决字母字符串问题  如何使用豆包 AI 练习托福雅思口语对练  智谱AI创意设计怎么用_智谱AI创意设计使用方法详细指南【教程】  千问怎么用提示词生成演讲稿_千问演讲稿提示词框架与开场【教程】  LeetCode算法:最长公共前缀问题全面解析  AI写作避坑指南:小说家应避免的AI使用与创作技巧  旅游营销AI:ChatGPT邮件营销策略,提升旅游业务转化率  Jetson SegNet: 语义分割深度探索与实践  AI威胁论:超人工智能ASI时代来临,人类如何应对?  利用 Google AI 进行图像元数据分析与整理  Sim.AI教程:构建智能客户支持助手  Google AI 在教育领域个性化学习路径的构建  LeetCode问题解析:移除回文子序列,掌握字符串技巧  AI怎么修复模糊视频 视频画质增强AI软件Topaz Video使用【教程】  n8n教程:如何用AI自动生成个性化简历  lovemo官网直达链接 lovemo网页版在线  网络安全警钟:揭秘“美足”背后隐藏的危机与防范  百度浏览器侧边栏ai怎么关 百度浏览器ai侧边栏隐藏  Gemini怎样连接Google账号_Gemini账号连接方法【方法】  AI驱动的Web应用测试:突破QA挑战,提升用户体验  Google Gemini 在跨时区团队管理中的应用技巧  千问AI赚钱指南:新手也能月入破万的实操路径解析!  手相解析:生命线的形状与意义详解,预示健康、财富和命运  ChatGPT 在电商产品描述批量生成中的应用  v0 Report深度测评:AI文档生成器的优缺点分析与实用指南  AI一键生成儿童绘本故事  DeepSeek如何编写Shell脚本 DeepSeek自动化运维指南  百度输入法总是弹出ai 百度输入法ai自动弹出关闭  歌曲分析:The Killers乐队的《Mr. Brightside》歌词深度解析  怎么用AI帮你为初创公司进行市场定位分析?  Excel Copilot:AI驱动的强大新功能与实用案例解析  Google AI Studio 中的提示词微调实验教程  研究学者如何利用现有资源提升学术影响力  P&ID图全解析:工艺流程图解读与应用指南  Notta AI: 提升效率的智能会议纪要工具  雷小兔ai智能写作如何生成文案_雷小兔ai智能写作文案生成场景选择【攻略】  Elon Musk会解决X平台上的机器人问题吗?塔罗牌预测  Xcode 26 Beta 新功能:集成 ChatGPT 代码助手全面测评  AI问卷调查生成工具有哪些_一键生成调研表单的AI工具推荐  豆包 AI 在英语单词高效背诵中的趣味应用  DeepSeek写简历怎么用_DeepSeek写简历使用方法详细指南【教程】  如何利用AI优化简历关键词?轻松通过ATS筛选系统  超频爱好者盛宴:液氮超频Xeon 28核处理器  Agentic Testing入门:使用Playwright和Claude Code构建自动化框架  泰米尔电影猜谜游戏:挑战你的电影知识极限!  在线奇幻名称生成器:打造独一无二的角色名  如何用AI帮你分析用户评论?3步挖掘用户真实需求  AI社交媒体自动化:n8n与HeyGen打造个性化内容引擎 

 2025-07-28

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

南京市珐之弘网络技术有限公司


南京市珐之弘网络技术有限公司

南京市珐之弘网络技术有限公司专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 87067657

 13565296790

 87067657@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.