java-pytorch 使用手动下载FashionMNIST数据集进行测试

java-pytorch 使用手动下载FashionMNIST数据集进行测试

    • 先定义训练数据和测试数据的位置
    • 查看一下读取到的标签数据格式
    • 使用loc和iloc访问下数据,便于下面操作
    • 使用read_image函数查看下图片的数据大小
    • 开始写数据集
    • 使用DataLoader去加载我们自己的数据
      • 看下加载后的dataloader数据形状
      • 循环查看下dataloader每个数据的信息
    • 写一个简单的模型,由Linear组成
    • 定义损失函数和优化器
    • 编写测试和训练方法
    • 开始训练
    • 保存模型
    • 加载模型
    • 使用加载的模型进行预测
      • 图片处理
    • 预测
    • 其他
      • 图片灰度处理转tensor
      • 测试某一张图片

  1. 手动下载FashionMNIST数据集,通过https://blog.csdn.net/m0_60688978/article/details/137085740转换为实际的图片和标注
  2. 目的是为了模拟实际业务中,我们往往需要自己采集图片数据和打标签的过程
  3. 因为FashionMNIST数据集图片是28x28,和对应的一个图片和类型的记录文件output.txt

先定义训练数据和测试数据的位置

annotations_file="../data/imageandlableTrain/output.txt"
img_dire="../data/imageandlableTrain"test_img_dire="../data/imageandlableTest"
test_annotations_file="../data/imageandlableTest/output.txt"

查看一下读取到的标签数据格式

import pandas as pdlables=pd.read_csv(annotations_file,header=None)
lables.head(10)
01
0Ankleboot1.jpg9
1T-shirttop2.jpg0
2T-shirttop3.jpg0
3Dress4.jpg3
4T-shirttop5.jpg0
5Pullover6.jpg2
6Sneaker7.jpg7
7Pullover8.jpg2
8Sandal9.jpg5
9Sandal10.jpg5

使用loc和iloc访问下数据,便于下面操作

imageName,lable=lables.loc[3,:]
imageName,lable
('Dress4.jpg', 3)
lables.iloc[2,1]
0

使用read_image函数查看下图片的数据大小

from torchvision.io import read_image
image1=read_image("../data/imageandlableTrain/T-shirttop2.jpg")
type(image1),image1.size(),image1[0].size(),image1
(torch.Tensor,torch.Size([3, 28, 28]),torch.Size([28, 28]),tensor([[[ 0,  0,  1,  ...,  1,  8,  0],[13,  0,  0,  ..., 10,  0,  0],[ 0,  0, 22,  ..., 10,  0,  1],...,[ 0,  0,  0,  ...,  0,  0,  0],[ 0,  0,  0,  ...,  0,  0,  0],[ 0,  0,  0,  ...,  0,  0,  0]],[[ 0,  0,  1,  ...,  1,  8,  0],[13,  0,  0,  ..., 10,  0,  0],[ 0,  0, 22,  ..., 10,  0,  1],...,[ 0,  0,  0,  ...,  0,  0,  0],[ 0,  0,  0,  ...,  0,  0,  0],[ 0,  0,  0,  ...,  0,  0,  0]],[[ 0,  0,  1,  ...,  1,  8,  0],[13,  0,  0,  ..., 10,  0,  0],[ 0,  0, 22,  ..., 10,  0,  1],...,[ 0,  0,  0,  ...,  0,  0,  0],[ 0,  0,  0,  ...,  0,  0,  0],[ 0,  0,  0,  ...,  0,  0,  0]]], dtype=torch.uint8))

开始写数据集

思路很简单,初始化的时候,将output.txt的数据读出来,然后在__getitem__返回单一图片的tensor数据和标签

这里需要注意的是:read_image的结果数据size是torch.Size([3, 28, 28]),而模型需要的[28,28],因此要返回image[0]

from torchvision.io import read_image
from torch.utils.data import Datasetclass CustomImageDataset(Dataset):def __init__(self):
#         获得所有的lablesself.labels=pd.read_csv(annotations_file,header=None)self.imageDir=img_diredef __len__(self):return len(self.labels)def __getitem__(self, idx):imageName,lable=self.labels.loc[idx,:]image=read_image("{}/{}".format(img_dire,imageName))image=image[0]return image,lable
class CustomImageDatasetTest(Dataset):def __init__(self):#         获得所有的lablesself.labels=pd.read_csv(test_annotations_file,header=None)self.imageDir=img_diredef __len__(self):return len(self.labels)def __getitem__(self, idx):imageName,lable=self.labels.loc[idx,:]image=read_image("{}/{}".format(test_img_dire,imageName))image=image[0]return image,lable

使用DataLoader去加载我们自己的数据

from torch.utils.data import DataLoader
train_dataloader = DataLoader(CustomImageDataset(), batch_size=2)
len(train_dataloader)
30000
test_dataloader = DataLoader(CustomImageDatasetTest(), batch_size=2)
len(test_dataloader)
5000

看下加载后的dataloader数据形状

for X, y in train_dataloader:print(f"Shape of X [N, C, H, W]: {X.shape}")print(f"Shape of y: {y.shape} {y.dtype}")break
Shape of X [N, C, H, W]: torch.Size([2, 28, 28])
Shape of y: torch.Size([2]) torch.int64

循环查看下dataloader每个数据的信息

for batch, (X, y) in enumerate(train_dataloader):print(X,batch,X.size(),y,type(y))if batch==2:break
---------------------------------------------------------------------------NameError                                 Traceback (most recent call last)Cell In[35], line 1
----> 1 for batch, (X, y) in enumerate(train_dataloader):2     print(X,batch,X.size(),y,type(y))3     if batch==2:NameError: name 'train_dataloader' is not defined

写一个简单的模型,由Linear组成

import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
class NeuralNetwork(nn.Module):def __init__(self):super().__init__()self.flatten = nn.Flatten()self.linear_relu_stack = nn.Sequential(nn.Linear(28*28, 512),nn.ReLU(),nn.Linear(512, 512),nn.ReLU(),nn.Linear(512, 10),)def forward(self, x):x = self.flatten(x)logits = self.linear_relu_stack(x)return logits
model = NeuralNetwork().to("cpu")
print(model)
NeuralNetwork((flatten): Flatten(start_dim=1, end_dim=-1)(linear_relu_stack): Sequential((0): Linear(in_features=784, out_features=512, bias=True)(1): ReLU()(2): Linear(in_features=512, out_features=512, bias=True)(3): ReLU()(4): Linear(in_features=512, out_features=10, bias=True))
)

定义损失函数和优化器

这里重点关注学利率,太低会爆

loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)

编写测试和训练方法

测试方法思路也很简单,就是在测试数据中逐一把数据传入到模型中,累计损失和正确率

这里要注意的是正确率的统计,就是预测正确的?累加(pred.argmax(1) == y).type(torch.float).sum().item()



训练思路:固定套路,直接copy

# 测试方法
def test(dataloader, model, loss_fn):size = len(dataloader.dataset)num_batches = len(dataloader)model.eval()test_loss, correct = 0, 0with torch.no_grad():for X, y in dataloader:
#             X, y = X.to(device), y.to(device)pred = model(X.float().unsqueeze(1))test_loss += loss_fn(pred, y).item()correct += (pred.argmax(1) == y).type(torch.float).sum().item()test_loss /= num_batchescorrect /= sizeprint(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
def train():for batch,(onedatas,lable) in enumerate(train_dataloader):model.train()pred=model(onedatas.float().unsqueeze(1))loss=loss_fn(pred,lable)lossitem=loss.item()# Backpropagationloss.backward()optimizer.step()optimizer.zero_grad()if batch % 100:print(f"loss {lossitem},batch is {batch}")

开始训练

思路就是套路照搬即可

#  训练
for t in range(10):print(f"Epoch {t+1}\n-------------------------------")train()test(test_dataloader, model, loss_fn)
print("Done!")

保存模型

# save model
torch.save(model.state_dict(),"model.pth")
print("Saved Model State to model.pth")
Saved Model State to model.pth
print(model)
NeuralNetwork((flatten): Flatten(start_dim=1, end_dim=-1)(linear_relu_stack): Sequential((0): Linear(in_features=784, out_features=512, bias=True)(1): ReLU()(2): Linear(in_features=512, out_features=512, bias=True)(3): ReLU()(4): Linear(in_features=512, out_features=10, bias=True))
)

加载模型

model = NeuralNetwork().to("cpu")
model.load_state_dict(torch.load("model.pth"))
<All keys matched successfully>

使用加载的模型进行预测

图片处理

  1. 要求灰度 2. 要求28*28 3. 数据是tensor
from PIL import Image# 打开原始图片
image = Image.open('lianxie.jpg')# 调整图片大小
new_size = (28,28) # 新的宽高像素值
resized_image = image.resize(new_size)# 转换成灰度图像
grayscaled_image = resized_image.convert("L")
grayscaled_image

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

transform_d = transforms.Compose([transforms.ToTensor()
])
image_t = transform_d(grayscaled_image)
plt.imshow(image_t[0])
<matplotlib.image.AxesImage at 0x1fabef58520>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测

可以看到output的最大值下表是5,即是预测结果,预实际相符

output=model(image_t)
output
tensor([[ 0.1207, -0.4304,  0.2356,  0.2038,  0.2823, -0.2736,  0.4910, -0.0614,-0.1314, -0.4034]], grad_fn=<AddmmBackward0>)

其他

图片灰度处理转tensor

import torch
import torchvision.transforms as transforms
from PIL import Image# 定义转换管道
grayscale_transform = transforms.Grayscale(num_output_channels=1)  # 灰度转换
tensor_transform = transforms.ToTensor()  # Tensor转换
resized_transform=transforms.Resize((28,28))# 读取图片
image = Image.open("lianxie.jpg")# 应用转换
gray_image = grayscale_transform(image)resized_gray_tensor = resized_transform(gray_image)
gray_tensor = tensor_transform(resized_gray_tensor)gray_tensor,gray_tensor.size()
output=model(gray_tensor)
output
tensor([[ 0.1208, -0.4305,  0.2355,  0.2039,  0.2823, -0.2737,  0.4913, -0.0619,-0.1308, -0.4036]], grad_fn=<AddmmBackward0>)

测试某一张图片

# 排查# Sandal13.jpg,5
# Sandal14.jpg,5image=read_image("{}/Sandal13.jpg".format(img_dire))imageData=image[0].unsqueeze(0)
print("unsqueeze: ",imageData)
print("unsqueeze after size : ",imageData.size())print("original size: ",image.size())output=model(imageData.float())print("output content is ",output)# argmax取值最大的下标
print(output.argmax(1))
# 结论
# 减少学习率即可
unsqueeze:  tensor([[[  0,   0,   0,   0,   0,   0,   0,   0,   1,   1,   0,   0,   3,   8,5,   0,   0,   0,   0,   0,   5,   0,   0,   3,   0,   4,   0,   0],[  0,   0,   0,   0,   0,   0,   0,   0,   2,   1,   0,   0,   0,   0,0,   0,   3,   5,   1,   1,   6,   1,   0,   0,   4,   0,   0,   4],[  0,   0,   0,   0,   0,   0,   0,   0,   3,   0,   0,   6,  12,   6,1,   3,   0,   1,   0,   0,   0,   1,   1,   0,   0,   0,   0,   4],[  0,   0,   0,   0,   0,   0,   0,   0,   7,   1,   0,   1,   1,   0,0,   0,   0,   0,   2,   0,   0,   0,   5,   3,   0,   2,   8,   0],[  0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   7,   0,   0,   0,5,  11,   2,   0,   6,   9,   0,   0,   3,   0,   7,   6,   5,   0],[  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,   5,   5,0,   0,   7,   0,   0,   9,   2,   0,   4,   0,   0,   0,   0,   0],[  0,   0,   0,   0,   0,   0,   0,   0,   9,   0,   0,   1,   0,   0,3,  29,  62,   3,   0,   3,   0,   0,   6,   0,   0,  20,   9,   0],[  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   9,   0,   0,96, 209, 143,  51,   1,   3,   0,   0,   6,   0,   2,  76,  57,   0],[  6,   0,   5,   7,   4,   0,   0,   7,   4,   0,   0,  11,  19, 167,218, 176, 197, 184,   0,   5,   0,  11, 121, 134, 152, 117,  75,   0],[  0,   0,   0,   0,   6,   0,   4,   0,   0,   0,   0,   7,  56, 219,168, 160, 204, 246,  95,  31, 105, 175, 199, 115,  18,   0,   5,   0],[  0,   7,   2,   8,  18,   0,   2,   8,   0,   5,   2,   0,   1, 182,245, 152, 158, 185, 235, 200, 175,  78,   8,  17,  23,   2,  13,   0],[  0,  15,   0,   0,   0,  16,   5,   0,   4,   0,  21,  14,  11,  48,230, 251, 240, 185, 221,  71,   0,  10,   0,   0,   0,   0,  12,   0],[  3,   0,   0,  31,   0,   0,  25, 120, 194,   0,   0,   0,   0,  19,171, 225, 230, 205, 222, 150,   8,   0,   1,  37,  42,  43,  61,  38],[  4,   7,   0,   0,   2, 140, 194, 186, 201, 165,  13,   0,  11,   0,0,  89, 135, 208, 180, 241, 178, 124, 132, 135, 161, 141, 143, 113],[  0,   3,   0,   0,   2, 107, 235, 196, 167, 219,  18,   8,  11,   0,6,  49, 203, 221, 137, 170, 112,  65,  59,  75,  52,  55,  80,  59],[  9,  13,   3,   2,   0,  11, 184, 127,   5, 197, 111,   0,  14,  97,109, 127, 148, 100,  89,  93,  64, 126, 106, 115,  87, 105, 115,  53],[ 40, 109, 121, 120, 106,  91, 198, 207, 121, 187, 255, 127, 126,  96,110,  71,  60,  93,  73,  74,  74,  73,  93,  60,  85,  82,  99,  40],[ 41,  72,  36,  56,  64,  78,  99,  69,  92,  92, 109,  51,  76,  75,84,  79, 104, 102,  74,  94,  94,  76, 105, 107,  60,  63,  87,  22],[ 21,  95,  88, 115,  84, 105,  82,  83,  61,  64,  79,  88,  94,  89,72,  88,  98,  92,  75, 103, 102,  72,  87,  92, 103,  99, 105,  14],[ 17,  84,  79,  90,  66, 104,  73,  97,  75,  95,  96,  91,  75,  78,74,  94,  59,  75,  70,  80,  81,  74,  81,  66,  47,  54,  70,   0],[  0,  78, 122, 127, 108, 109,  70,  90,  93, 102,  94,  85, 103, 115,128, 129, 132, 146, 136, 126, 133, 154, 173, 164, 180, 153, 110,   9],[  0,   4,   6,  21,  70, 108, 103, 108, 105, 103,  95,  86,  98,  61,54,  37,  13,   7,   0,   0,   0,   8,  23,  31,  17,  21,  15,   0],[  0,   6,   2,   2,   0,   0,   0,   5,   0,   8,   0,   0,   5,   0,0,   0,  10,   0,   1,   3,   2,   0,   0,   4,   0,   9,   0,   0],[  0,   1,   0,  16,   0,   0,   3,   1,   0,  15,   0,   0,   2,   3,10,   0,   0,   0,   3,   0,   0,   3,   0,   0,   0,  10,   0,   9],[  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0],[  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0],[  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0],[  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0]]],dtype=torch.uint8)
unsqueeze after size :  torch.Size([1, 28, 28])
original size:  torch.Size([3, 28, 28])
output content is  tensor([[-6.7115,  1.3163, -7.2377, -1.6586,  2.7382,  3.2748, -6.3696, -0.6497,-7.3979, -1.4042]], grad_fn=<AddmmBackward0>)
tensor([5])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/780343.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FANUC机器人故障诊断—报警代码(一)

一、SRVO-050碰撞检测报警 [原因]检测出碰撞 [对策] 1.确认机器人是否碰撞。 2.确认是否正确进行了负载设定。 3.确认是否有过载、过度的加速度附加指令。 4.在长期停用后启动&#xff0c;或者外部气温较低时发生该报警。启动后&#xff0c;先短时间内低速运转设备&#…

vue3使用UEditorPlus 、后端配置、上传图片等处理

前端安装 vue3安装vue-ueditor-wrap // vue-ueditor-wrap v3 仅支持 Vue 3 npm i vue-ueditor-wrap3.x -S // or yarn add vue-ueditor-wrap3.x 下载 UEditorPlus 仓库地址 把dist文件复制到vue3项目中的public下&#xff0c;重命名为UEditorPlus UEditorPlus文档 在main.…

ArcGIS支持下SWAT与CENTURY模型的结合:流域水碳氮综合模拟

目录 专题一 流域水碳氮建模 专题二 数据准备 专题三 流域水模拟 专题四 流域氮模拟 专题五 流域碳模拟 专题六 模型结果分析及地图制作 更多应用 基于ArcGIS的SWAT模型是一类比较典型的流域模型&#xff0c;结合SWAT模型和生物地球化学循环模型可以实现流域水碳氮综合模…

根据实例逐行分析NIO到底在做什么

Selector&#xff08;选择器&#xff09;是 Channel 的多路复用器&#xff0c;它可以同时监控多个 Channel 的 IO 状况&#xff0c;允许单个线程来操作多个 Channel。Channel在从Buffer中获取数据。 选择器、通道、缓冲池是NIO的核心组件。 一、新建选择器 此时选择器内只包含…

Nginx-记

Nginx是一个高性能的web服务器和反向代理服务器&#xff0c;用于HTTP、HTTPS、SMTP、POP3和IMAP协议。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。 &#xff08;1&#xff09;更快 这表现在两个方面&#xff1a;一方面&#xff0c;在正常情况下&…

【OpenGL】使用 python + Qt + OpenGL 的现代渲染

伴随资源 目录 一、说明二、 关于PyQt6.x2.1 QOpenGLWidget详细说明2.2 绘画技巧 三、PyOpenGL四、OpenGL 管线五、Python集成开发环境5.1 Emacs配置5.2 pycharm环境 六、你好&#xff0c;OpenGL&#xff01;七、QGL控件八、平截头体.svg九、定义几何9.1 立即模式与保留模式9…

OpenAI发布Voice Engine模型!用AI合成你的声音!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

比torchvision更强大,从timm库引用预训练模型和本地加载的方法

1&#xff0c;介绍 torchvision是大家最常用的预训练模型来源&#xff0c;但是其包含的预训练模型种类很少&#xff0c;往往并不能满足研究者们的需求。 而timm库提供了一个更强大的替代选项。 利用如下代码查询 import timmprint(len(timm.list_models())) 输出 1032 可…

Android Studio 2023.2.1版本 kotlin编译报错踩坑

1、需求 由于最近在整理项目&#xff0c;做一些公共基础组件Maven仓库封装&#xff0c;由于之前项目jar包和kotlin版本很老&#xff0c;kotlin版本1.3.72版本 Gradle使用5.4.1 Android Studio版本是2023.2.1&#xff0c;分别依次顺序如下图所示。 如下图所示 2、分析编译报错…

如何利用大模型LLM辅助,使用Python完成将CSV快速导入MySQL数据库

目录 一、适合场景 二、开发过程说明 三、功能使用流程 四、代码 1、安装python依赖库 2、完整代码段 一、适合场景 无废话&#xff0c;CSV中有少量不合规数据需要手工处理可利用此方法&#xff0c;适合有点经验的程序员&#xff0c;可以不熟Python&#xff0c;思路还是要…

【动手学深度学习-pytorch】-9.3深度循环神经网络

到目前为止&#xff0c;我们只讨论了具有一个单向隐藏层的循环神经网络。 其中&#xff0c;隐变量和观测值与具体的函数形式的交互方式是相当随意的。 只要交互类型建模具有足够的灵活性&#xff0c;这就不是一个大问题。 然而&#xff0c;对一个单层来说&#xff0c;这可能具有…

Oracle 19C RAC集群补丁升级

文章目录 一、补丁包概述二、OPatch检查和更新Grid用户更新OPatchOracle用户更新OPatch 三、验证Oracle Inventory的有效性四、运行 OPatch 冲突检查五、运行opatch命令检查GI HOME下是否有足够的空间六、补丁冲突检测与解决&#xff08;修补程序&#xff09;七、使用root用户应…

Linux - 第三节

改变用户类型 su 仅单纯的进行身份变化 依旧处于普通用户里面 su - 进行重新登录更改身份 退出用exit / ctrld su 用户名 改成成其他身份 对一条命令进行提权 sudo command r:可读 w:可写 x:可执行 -:对应的权限位置&#xff0c;没有权限 去掉所有权限 chmod u…

多视图三维重建-SFM简介

背景 掌握传统的多视图三维重建基本流程 总体流程 多视图三维重建的Pipieline如下图&#xff0c;总共分为四个步骤&#xff1a; 拍摄场景多视角的图像建立这些图像之间的联系&#xff08;Data Association&#xff09;SFM稀疏重建MVS稠密重建 Data Association 建立图像…

向开发板上移植ip工具:将ip工具移植到开发板系统中

一. 简介 前面一篇文章对 ip工具源码进行了交叉编译&#xff0c;生成了ip工具。文章如下&#xff1a; 向开发板上移植ip工具&#xff1a;交叉编译 ip工具-CSDN博客 本文对生成的 ip工具进行移植&#xff0c;即移植到开发板系统中&#xff0c;并确定是否可用。 二. 向开发板…

Nagios工具

一 nagios 相关概念 Nagios 是一款开源的免费网络监视工具&#xff0c;能有效监控 Windows、Linux 和 Unix 的主机状态&#xff0c;交换机路由器等网络设置&#xff0c;打印机等。在系统或服务状态异常时发出邮件或短信报警第 一时间通知网站运维人员&#xff0c;在状态恢复后…

顶顶通呼叫中心中间件-声音编码自适应配置方法(mod_cti基于FreeSWITCH)

顶顶通呼叫中心中间件-声音编码自适应配置方法讲解(mod_cti基于FreeSWITCH) 声音编码自适应介绍 声音编码自适应&#xff0c;通常在语音通信和音频处理领域中指的是一种能够根据信号特性和传输环境自动调整编码参数的技术。其目的是在不同的网络状况和音质要求下&#xff0c;…

5-规范设计(下):commit信息风格迥异、难以阅读,如何规范?

我们在做代码开发时&#xff0c;经常需要提交代码&#xff0c;提交代码时需要填写 Commit Message&#xff08;提交说明&#xff09;&#xff0c;否则就不允许提交。 所以在 Go 项目开发时&#xff0c;一个好的 Commit Message 至关重要&#xff1a; 可以使自己或者其他开发人…

基于SSM的百货中心供应链管理系统设计与实现(论文+源码)_kaic

摘 要 社会发展日新月异&#xff0c;用计算机应用实现数据管理功能已经算是很完善的了&#xff0c;但是随着移动互联网的到来&#xff0c;处理信息不再受制于地理位置的限制&#xff0c;处理信息及时高效&#xff0c;备受人们的喜爱。本次开发一套百货中心供应链管理系统有管理…