吴恩达深度学习课程二: 改善深层神经网络 第三周:超参数调整,批量标准化和编程框架 课后习题和代码实践

news/2025/11/24 13:35:55/文章来源:https://www.cnblogs.com/Goblinscholar/p/19263775

此分类用于记录吴恩达深度学习课程的学习笔记。
课程相关信息链接如下:

  1. 原课程视频链接:[双语字幕]吴恩达深度学习deeplearning.ai
  2. github课程资料,含课件与笔记:吴恩达深度学习教学资料
  3. 课程配套练习(中英)与答案:吴恩达深度学习课后习题与答案

本篇为第二课第三周的课程习题和代码实践部分笔记。


1. 理论习题:独热编码

还是先上链接:
【中英】【吴恩达课后测验】Course 2 - 改善深层神经网络 - 第三周测验
因为本周内容大多是一些补充,因此习题也大多只是之前了解到的死知识,就不再多提了。
这部分补充一个之前出现的技术:独热编码

1.1 独热编码(One-Hot Encoding)

之前在多值预测与多分类这部分里,我们提到过,在多分类的情况下, 使用独热编码来表示各个分类,现在就来展开一下这个技术。
为了让解释更直观,我们全程使用同一个实例:

例子:识别动物类别,有三类:猫(Cat)、狗(Dog)、兔子(Rabbit)。
我们用这个例子贯穿整个独热编码的说明。

(1)用独热编码表示分类的直接形式

在多分类中,一个类别就是一个“离散的标签”,没有数值大小,也不存在“比谁大一点”的概念
但神经网络输出的是一组数字,为了让网络能理解“哪个类别是正确答案”,我们就需要把“猫/狗/兔子”变成神经网络能处理的格式。

独热编码就是最直接的方式:每一个类别对应一个位置,正确的那个位置为 1,其余为 0。
来看看具体怎么做:现在对我们的动物识别例子做独热编码处理,结果如下:

类别 独热编码
猫 Cat [1, 0, 0]
狗 Dog [0, 1, 0]
兔 Rabbit [0, 0, 1]

其中:

  • 三个神经元对应三个分类
  • “1”表示正确分类,“0”表示不是
  • 标签永远只有一个位置是 1

这就是“独热”:只有一个地方热
这是它对多分类的直接表现形式。

(2)为什么二分类不使用独热编码?

那你可能会问:
“既然多分类用独热,那二分类是不是也能写成 [1,0][0,1]?”
答案:理论上可以,实践中不会这么做
原因很简单:没必要
简单展开一下:
二分类的本质是:是否属于某一类(比如“是不是猫”)

只需要一个神经元 + sigmoid,就能表达“是的概率”。
这意味着 一个神经元就能表达整个二分类的状态

这种结构浪费计算,还会带来梯度重复问题。
什么叫“梯度重复”?,这是softmax在二分类应用中出现的问题。

假设某张图真实标签是:

猫 → [1, 0]

而模型预测是:

ŷ = [0.4, 0.6]

也就是模型认为“不是猫”的概率比“是猫”还高。
根据交叉熵,我们得到两个神经元的损失项:

L1 = -1 * log(0.4)
L2 = -0 * log(0.6)

乍看只第一个有影响。
但真正计算梯度时,Softmax 会让两个神经元一起参与:

  • 第 1 个神经元(猫)要把概率从 0.4 推到更高
  • 第 2 个神经元(不是猫)要把概率从 0.6 推到更低

于是反向传播时两个神经元都会更新:

  • 第一个神经元:“我应该更强一点”
  • 第二个神经元:“我应该更弱一点”
    这就产生了两个方向相反但意义重复的梯度

而这两个神经元本质上是一件事:

P(不是猫) = 1 − P(是猫)

所以,这种结构就是让网络:

  • 学一次“猫应该更强”
  • 再学一次“不是猫应该更弱”

这其实是同一条语义的两次更新

这就是二分类使用softmax带来的梯度重复现象:
它让模型参数增加,训练更慢,softmax还让两个输出互相牵连,一个升另一降,让本来很简单的二分类被人为增加了耦合难度。

(3) 多分类不使用独热编码的影响

那多分类为什么不能像二分类一样直接写成0,1,2呢?
就像这样:

类别 非独热写法
0
1
2

你可能已经发现了问题所在,我们在一开始就强调了:类别不存在“比谁大一点”的概念
使用上面这种分类方法带俩的严重问题就是:神经网络会错误地认为“兔 > 狗 > 猫”

再简单展开一下:
在这种分类方式下,模型会把 “误差”理解为数值距离

例如真实标签是“兔 = 2”,模型预测成“猫 = 0”。
模型认为误差 = |2 − 0| = 2
那预测成“狗 1”误差就会变小。
于是, 模型会错误地认为预测成“狗”比预测成“猫”更接近正确答案,带来梯度的混乱
但实际上,我们知道:“猫”和“狗”与“兔”之间没有“更近”的关系,它们应该是三种平行的、不可比较的类别
所以这种写法会导致训练逻辑错误,学习方向混乱,效果极差。

(4)独热编码对多分类的适配性

现在再来看看独热编码的优势。
继续使用我们动物识别例子:
真实标签“兔子” → [0, 0, 1]
假设模型输出的是 Softmax 后的概率:

预测为:猫   0.1
预测为:狗   0.2
预测为:兔   0.7

Softmax 输出为:

ŷ = [0.1, 0.2, 0.7]

真实标签为:

y  = [0, 0, 1]

交叉熵损失就很自然:

Loss = - log(预测为兔的概率) = -log(0.7)

只有正确类别那一项会参与计算,其余项为 0,不影响损失。

但重点来了:虽然损失项只有一项,但梯度来自所有类别
上面的损失表达式容易让人误解:“只有一项有用,那是不是梯度也只来自那一项?”
其实不是。

我们继续看:
Softmax + CrossEntropy 的梯度公式非常简单:

\[\frac{\partial L}{\partial z_i} = \hat{y}_i - y_i \]

代入我们的例子:

  • 对“猫”神经元:\(0.1 - 0 = 0.1\)
  • 对“狗”神经元:\(0.2 - 0 = 0.2\)
  • 对“兔”神经元:\(0.7 - 1 = -0.3\)
    可以看到:
  • “兔” 的梯度是负的 → 相关参数会变大(让概率更接近 1)
  • “猫”和“狗”的梯度是正的 → 相关参数会变小(让概率更接近 0)

这恰好符合我们对多分类的直观理解: 正确类变得更确定,其他类一起被压下去。

这就是多分类中,独热编码,softmax,交叉熵形成的更新链条,我们在下面的实践部分就能感受到它的效果。

2. 代码实践

在课程要求里,这周的实践作业是Tensorflow的入门,主要以了解Tensorflow的基本原理和语法为主,还是把这位博主的链接放在前面,介绍了使用Tensorflow构建神经网络的过程。
【中文】【吴恩达课后编程作业】Course 2 - 改善深层神经网络 - 第三周作业

虽然依然使用Pytorch来进行演示,但随着引入Tensorflow框架,之后课程内容对此的介绍和使用也会增加。因此,之后我都会在最后附上一个Tensorflow版本的代码。

2.1 多分类数据集

为了演示本周的内容,我们暂时放下之前的猫狗二分类数据集。
这次,我们使用一个新的数据集:手写数字图像识别
你可能之前已经知道这个数据集了,它并不需要我们和之前一样在网上寻找数据集下载。
pytorch内置了这个经典数据集的下载链接,我们可以直接通过API下载它到项目目录:

from torchvision import datasets, transforms  
from torch.utils.data import DataLoader
# 载入训练数据集  
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)  
# 载入测试数据集  
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)

运行后,你就会在你设置的root路径中发现这样的一个文件夹:
image.png
这是一个十分类数据集,包含七万张手写数字图像。可以以此对手写数字的图像进行分类,如果训练的模型较为成功,那么我们就可以得到一个可以识别手写数字的分类器。

2.2 网络结构

根据我们在本周所了解的内容,再结合数据集的情况,我们设计新的网络结构如下:

class NeuralNetwork(nn.Module):  def __init__(self):  super(NeuralNetwork, self).__init__()  self.flatten = nn.Flatten()  self.hidden1 = nn.Linear(28*28, 512)  # 灰度图只有一个通道来表示亮暗程度,不用像彩色图像一样乘3。self.hidden2 = nn.Linear(512, 256)  self.hidden3 = nn.Linear(256, 128)  self.hidden4 = nn.Linear(128, 32)  self.relu = nn.ReLU()  # 输出层(使用Softmax进行多分类)  self.output = nn.Linear(32, 10)  # 输出10个类别(0-9)  self.softmax = nn.Softmax(dim=1) # dim=1:对每一行(即每个样本的所有类别分数)进行计算,将每个类别的分数转化为概率。init.xavier_uniform_(self.output.weight)  def forward(self, x):  x = self.flatten(x)  x = self.relu(self.hidden1(x))  x = self.relu(self.hidden2(x))  x = self.relu(self.hidden3(x))  x = self.relu(self.hidden4(x))  x = self.output(x)  x = self.softmax(x)  # 使用Softmax输出类别概率  return x

2.3 损失函数和其他设置

# 迭代设置
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)  
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
# 图像较简单,因此增加批次大小到64# 损失函数和优化器  
criterion = nn.CrossEntropyLoss()  # 多分类使用交叉熵损失  
optimizer = optim.Adam(model.parameters(), lr=0.001) # 优化器默认选择Adam
num_epochs = 10 # 训练十轮

这里要单独说明的是,我们上面了解到的对多分类的独热编码就被封装在CrossEntropyLoss损失函数的设置里,它内部会自动把标签整数转为独热的形式进行计算。

2.4 第一次结果分析: 多分类

现在,我们根据上面的设置,来看看训练结果:
image.png
如果你看过之前的几次代码实践,可能会有一些疑惑,为什么几乎相同的配置下,猫狗二分类的准确率最高才刚刚到70%,现在都扩展到十分类并简化了网络结构的情况下,准确率却在90%以上?
很明显,二者最大的区别就是数据集不同。
我们来解释一下为什么手写数字图像识别的训练效果这么好:

  • 猫狗数据集:图像复杂、背景多变、光照、姿势都可能不同,样本间差异大,网络需要学习的特征复杂,因此训练难度高,准确率提升较慢。
  • 手写数字 MNIST 数据集:图像统一大小、灰度处理,数字相对居中,背景干净,样本间差异小,网络很容易学习到区分特征,因此即使网络结构相对简单,也能快速达到高准确率。

简单来说,就是手写数字的数据好,图像简单,而数据的可分性和特征明确程度直接决定了训练效果。
因此,MNIST也常常作为图神经网络的入门教程,即使我们使用的是全连接网络,也能达到较高的准确率,甚至你使用sigmoid和二分类交叉熵也能达到较好的拟合效果。

究其根本,数据好,就像品质极佳的原材料,就是水煮一下,也十分美味。
20251124114508842

2.5 加入批量标准化

我们本周了解了batch归一化,知道了它能起到加速训练,同时有轻微正则化的作用。
现在,我们就再把BN加入数字图像识别模型。
在Pytorch中,BN也被封装在网络结构模块里,完善后如下:

class NeuralNetwork(nn.Module):  def __init__(self):  super(NeuralNetwork, self).__init__()  self.flatten = nn.Flatten()  self.hidden1 = nn.Linear(28 * 28, 512)  self.bn1 = nn.BatchNorm1d(512)  # 第一层的BNself.hidden2 = nn.Linear(512, 256)  self.bn2 = nn.BatchNorm1d(256)  # 第二层的BNself.hidden3 = nn.Linear(256, 128)  self.bn3 = nn.BatchNorm1d(128)  # 第三层的BNself.hidden4 = nn.Linear(128, 32)  self.bn4 = nn.BatchNorm1d(32)  # 第四层的BNself.relu = nn.ReLU()  self.output = nn.Linear(32, 10)  self.softmax = nn.Softmax(dim=1)  init.xavier_uniform_(self.output.weight)  # 把BN加入传播过程def forward(self, x):  x = self.flatten(x)  x = self.hidden1(x)  x = self.bn1(x)  # 这里 x = self.relu(x)  x = self.hidden2(x)  x = self.bn2(x)  # 这里x = self.relu(x)  x = self.hidden3(x)  x = self.bn3(x)  # 这里x = self.relu(x)  x = self.hidden4(x)  x = self.bn4(x)  # 这里x = self.relu(x)  x = self.output(x)  x = self.softmax(x)  return x

于此同时,我们记得BN在训练和测试中对参数的使用有差别,测试中会使用训练中的全局均值和全局方差。
而这个逻辑是通过训练模式和评估模式的转换完成的:

model.train()  # 训练中维护全局 BN 参数
····训练代码
model.eval()   # 测试中使用固定全局 BN 参数

现在我们再来看看结果。

2.6 第二次结果分析:加入BN

来看看加入BN前后的对比:
20251124124510355
经过多次测试,可以较明显的发现,BN起到了加速训练的作用,在相同的其他配置下,使用BN的模型准确率也高于不使用BN。

3.附录

3.1 PyTorch版:数字图像识别模型代码

import torch  
import torch.nn as nn  
import torch.optim as optim  
from torchvision import datasets, transforms  
from torch.utils.data import DataLoader  
from torch.nn import init  
import matplotlib.pyplot as plt  transform = transforms.Compose([  transforms.ToTensor(),  transforms.Normalize((0.5,), (0.5,))  
])  
# 载入训练数据集  
train_dataset = datasets.MNIST(  root='./data',  train=True,  download=True,  transform=transform  
)  
test_dataset = datasets.MNIST(  root='./data',  train=False,  download=True,  transform=transform  
)  
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)  
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)  class NeuralNetwork(nn.Module):  def __init__(self):  super(NeuralNetwork, self).__init__()  self.flatten = nn.Flatten()  self.hidden1 = nn.Linear(28 * 28, 512)  self.bn1 = nn.BatchNorm1d(512)  self.hidden2 = nn.Linear(512, 256)  self.bn2 = nn.BatchNorm1d(256)  self.hidden3 = nn.Linear(256, 128)  self.bn3 = nn.BatchNorm1d(128)  self.hidden4 = nn.Linear(128, 32)  self.bn4 = nn.BatchNorm1d(32)  self.relu = nn.ReLU()  self.output = nn.Linear(32, 10)  self.softmax = nn.Softmax(dim=1)  init.xavier_uniform_(self.output.weight)  def forward(self, x):  x = self.flatten(x)  x = self.hidden1(x)  x = self.bn1(x)  x = self.relu(x)  x = self.hidden2(x)  x = self.bn2(x)  x = self.relu(x)  x = self.hidden3(x)  x = self.bn3(x)  x = self.relu(x)  x = self.hidden4(x)  x = self.bn4(x)  x = self.relu(x)  x = self.output(x)  x = self.softmax(x)  return x  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")  
model = NeuralNetwork().to(device)  criterion = nn.CrossEntropyLoss()  
optimizer = optim.Adam(model.parameters(), lr=0.001)  num_epochs = 10  
train_losses, train_accuracies, test_accuracies = [], [], []  
# 训练  
for epoch in range(num_epochs):  model.train()  running_loss = 0.0  correct_train = 0  total_train = 0  for images, labels in train_loader:  images, labels = images.to(device), labels.to(device)  optimizer.zero_grad()  outputs = model(images)  loss = criterion(outputs, labels)  loss.backward()  optimizer.step()  running_loss += loss.item() * images.size(0)  _, predicted = torch.max(outputs, 1)  total_train += labels.size(0)  correct_train += (predicted == labels).sum().item()  epoch_loss = running_loss / len(train_loader.dataset)  train_accuracy = correct_train / total_train  train_losses.append(epoch_loss)  train_accuracies.append(train_accuracy)  # 测试  model.eval()  correct_test = 0  total_test = 0  with torch.no_grad():  for images, labels in test_loader:  images, labels = images.to(device), labels.to(device)  outputs = model(images)  _, predicted = torch.max(outputs, 1)  total_test += labels.size(0)  correct_test += (predicted == labels).sum().item()  test_accuracy = correct_test / total_test  test_accuracies.append(test_accuracy)  print(f"Epoch {epoch + 1}/{num_epochs} | Loss: {epoch_loss:.4f} | "          f"Train Acc: {train_accuracy:.4f} | Test Acc: {test_accuracy:.4f}")  # 可视化  
plt.figure(figsize=(10, 5))  
plt.plot(train_losses, label='Train Loss', marker='o')  
plt.plot(train_accuracies, label='Train Accuracy', marker='x')  
plt.plot(test_accuracies, label='Test Accuracy', marker='s')  
plt.title('Training Loss & Accuracy')  
plt.xlabel('Epoch')  
plt.ylabel('Value')  
plt.ylim(0, max(max(train_losses), 1.0) + 0.1)  
plt.grid(True)  
plt.legend()  
plt.show()

3.2 Tensorflow版:数字图像识别模型代码

import tensorflow as tf  
from tensorflow.keras import layers, optimizers, losses  
import matplotlib.pyplot as plt  # 载入 MNIST 数据  
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()  
# 定义模型类  
class NeuralNetwork(tf.keras.Model):  def __init__(self):  super(NeuralNetwork, self).__init__()  self.flatten = layers.Flatten()  self.rescale = layers.Rescaling(1. / 127.5, offset=-1)  # [-1,1] 归一化  self.hidden1 = layers.Dense(512)  self.bn1 = layers.BatchNormalization()  self.hidden2 = layers.Dense(256)  self.bn2 = layers.BatchNormalization()  self.hidden3 = layers.Dense(128)  self.bn3 = layers.BatchNormalization()  self.hidden4 = layers.Dense(32)  self.bn4 = layers.BatchNormalization()  self.output_layer = layers.Dense(10, activation='softmax')  def call(self, x, training=False):  x = self.flatten(x)  x = self.rescale(x)  x = self.hidden1(x)  x = self.bn1(x, training=training)  x = tf.nn.relu(x)  x = self.hidden2(x)  x = self.bn2(x, training=training)  x = tf.nn.relu(x)  x = self.hidden3(x)  x = self.bn3(x, training=training)  x = tf.nn.relu(x)  x = self.hidden4(x)  x = self.bn4(x, training=training)  x = tf.nn.relu(x)  x = self.output_layer(x)  return x  # 实例化模型  
model = NeuralNetwork()  # 编译模型:加设置  
model.compile(optimizer=optimizers.Adam(learning_rate=0.001),  loss=losses.SparseCategoricalCrossentropy(),  metrics=['accuracy'])  # 训练模型  
num_epochs = 10  
batch_size = 64  
history = model.fit(x_train, y_train,  validation_data=(x_test, y_test),  epochs=num_epochs,  batch_size=batch_size)  # 可视化训练曲线  
plt.figure(figsize=(10, 5))  
plt.plot(history.history['loss'], label='Train Loss', marker='o')  
plt.plot(history.history['accuracy'], label='Train Accuracy', marker='x')  
plt.plot(history.history['val_accuracy'], label='Test Accuracy', marker='s')  
plt.title('Training Loss & Accuracy')  
plt.xlabel('Epoch')  
plt.ylabel('Value')  
plt.ylim(0, max(max(history.history['loss']), 1.0) + 0.1)  
plt.grid(True)  
plt.legend()  
plt.show()

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

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

相关文章

NSCT分解与重建MATLAB实现

一、环境配置工具箱安装下载NSCT工具箱(Nonsubsampled Contourlet Toolbox)解压后添加到MATLAB路径: addpath(NSCT_Toolbox\);关键函数说明 nsctdec: NSCT分解函数 nsctrec: NSCT重构函数 wthcoefsp: 阈值处理函数(…

BAT54S-ASEMI可直接替代安世BAT54S-QR

BAT54S-ASEMI可直接替代安世BAT54S-QR编辑:ll BAT54S-ASEMI可直接替代安世BAT54S-QR 型号:BAT54S 品牌:ASEMI 封装:SOT-23 正向电流:0.2A 反向电压:30V 正向压降:0.55V~0.95V 引线数量:2 芯片个数:1 芯片尺寸…

我们被主机厂坑掉几百万的那一年

上策伐谋,中策伐交:一个质量人的江湖生存指南 之前我写过一篇《逢年过节要祈祷》,讲的是处理客户投诉的经历,没想到引起了不少同行的共鸣,特别是汽车零部件行业的兄弟们。 其实大家都明白,只要是做这行,客户投诉…

深入解析:【经验】Word/WPS|用邮件合并批量填写表格或教案,单个Word导出成多个文件(包含插入图片的教程)

深入解析:【经验】Word/WPS|用邮件合并批量填写表格或教案,单个Word导出成多个文件(包含插入图片的教程)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; displ…

LTE系统资源分配MATLAB实现示例

LTE系统资源分配MATLAB实现示例(基于OFDMA的动态调度)一、系统架构设计 本方案采用模块化设计,包含以下核心模块:信道建模模块:生成多径衰落信道响应 CQI反馈模块:基于SNR计算信道质量指示 调度算法模块:实现比…

java 和C语言啥区别

Java 和 C 语言的核心区别在于内存管理方式与执行环境:C 是需手动管理内存的编译型语言,更贴近硬件;Java 是自动垃圾回收的半编译半解释型语言,跨平台性更强。 具体关键区别可从以下4点对比: 1. 内存管理:C语言:…

科研院校选购指南:小型高低温试验箱,哪个厂家精度更高、更靠谱?

在科研与教学领域,数据的准确性是生命线。许多高校、研究所的老师和同学们在选购小型高低温试验箱时,常被一个问题困扰:市场上品牌这么多,究竟哪家的设备控温精度更高、长期运行更稳定,更适合我们的科研需求?今天…

2025 年 11 月二手车市场权威推荐榜:昆山二手车,上海二手车,浙江二手车,太仓二手车,精选车源与高性价比之选

2025 年 11 月二手车市场权威推荐榜:昆山二手车,上海二手车,浙江二手车,太仓二手车,精选车源与高性价比之选 随着汽车消费观念的成熟和环保意识的增强,二手车市场正迎来前所未有的发展机遇。2025 年的中国二手车…

矢量字库应用全攻略:新手入门到高手实操一本通!

矢量字库是设计工作的“隐形利器”,它能确保文字在不同场景下始终保持清晰锐利。但对于初学者来说,如何正确使用矢量字库常常存在困惑。本篇教程将系统梳理矢量字库的应用逻辑,从最基础的文件格式认知开始,逐步深入…

2025 年 11 月 PVC 地板厂家权威推荐榜:导电防静电/同质透心/复合商用/磁性自沉式,精选耐用环保材质与创新工艺解析

2025 年 11 月 PVC 地板厂家权威推荐榜:导电防静电/同质透心/复合商用/磁性自沉式,精选耐用环保材质与创新工艺解析 随着现代建筑对功能性地面材料需求的不断提升,PVC 地板行业在技术创新与环保标准方面取得了显著进…

逢年过节都要祈祷

在某外资汽车零部件企业工作的那些年,无论在质量部还是项目部,都是成天和客户打交道,也经常面对各种各样的客户投诉。 尤其是当质量经理的那些年,每年都要被客户在油锅上炸几回。有产品质量投诉,也有非产品质量投…

2025 年 11 月建筑加固厂家权威推荐榜:碳纤维加固、粘钢加固,专业工艺与持久安全的高效解决方案

2025 年 11 月建筑加固厂家权威推荐榜:碳纤维加固、粘钢加固,专业工艺与持久安全的高效解决方案 随着我国城市化进程的不断推进和既有建筑存量持续增长,建筑加固行业正迎来前所未有的发展机遇。根据行业数据显示,我…

在ubuntu中使用新世纪五笔输入法

这是一个关于在ubuntu中使用新世纪五笔输入法的随笔。 This is an essay on using New Century Wubi Input in Ubuntu. 在以前,有搜狗输入法可以使用。但是实际上,搜狗输入法已经几乎没有人维护了。于是在fcitx 5的时…

python: 安装pyautogui

一,安装所需的linux库 # apt install python3-tk python3-dev二,安装pyautogui $ pip install pyautogui

想要中山中空阳光板优惠?查行情享高达20%折扣

想要中山中空阳光板优惠?查行情享高达20%折扣近年来,随着绿色建筑与节能材料需求的持续上升,聚碳酸酯板材在华南地区应用日益广泛。作为珠江口西岸的重要城市,中山凭借其优越的地理位置和完善的建材产业链,成为中…

数字化转型:小企业反而更有优势?

这几年,“数字化转型”听起来高大上,但其实已经渗透到我们身边。很多一两百人的小厂,同时上五六个管理系统都不稀奇了。大企业就更不用说了,资源足,动作更快。 但有意思的是:在质量管理数字化这件事上,小企业反…

数据告诉你:不会解决问题,是企业最大的痛点!

最近看到一份汽车行业的报告,结果让我有点吃惊。 这份《质量2020》报告显示,无论是汽车主机厂还是零部件供应商,大家都把“问题解决能力”排在了影响质量因素的第一位。 你可能觉得这只是汽车行业的问题?别急,继续…

完整教程:未来之窗昭和仙君(四十一)开发收银系统15k大小——东方仙盟筑基期

完整教程:未来之窗昭和仙君(四十一)开发收银系统15k大小——东方仙盟筑基期2025-11-24 13:05 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x…

2025年质量好的央企职业装定制最新TOP厂家排名

2025年质量好的央企职业装定制最新TOP厂家排名行业背景与市场趋势随着中国经济的持续发展和企业形象意识的不断提升,央企职业装定制市场呈现出快速增长态势。据中国服装协会最新数据显示,2024年中国职业装市场规模已…