李沐机器学习系列1--- 线性规划

1 Introduction

1.1 线性回归函数

典型的线性回归函数
f ( x ) = w ⃗ ⋅ x ⃗ f(x)=\vec{w} \cdot \vec{x} f(x)=w x
现实生活中,简单的线性回归问题很少,这里有一个简单的线性回归问题。房子的价格和房子的面积以及房子的年龄假设成线性关系。
p r i c e = w a r e a ∗ a r e a + w a g e + b price = w_{area}*area + w_{age}+b price=wareaarea+wage+b

1.2 损失函数

确定了变量和结果之间的大致关系以后,我们需要通过优化的方法进行迭代优化求解。
让我们从优化的角度来看这个问题。
c o s t = 0.5 ∑ i n ( w ⃗ ∗ x − y i ) T Q ( w ⃗ ∗ x − y i ) cost = 0.5\sum_i^n(\vec{w}*x-y^{i})^TQ(\vec{w}*x-y^{i}) cost=0.5in(w xyi)TQ(w xyi)
这是一个典型的QP问题,可以使用迭代的方法找到最优解。
在QP问题中,往往采用wolfe规则,但是这往往使用到全部的数据,在大规模的机器没有办法这么做,采用SGD的方法。

1.3 随机梯度下降

对于方程求解问题,典型的方法是牛顿迭代法。
基础的牛顿迭代法可以这么理解:
0 − f ( x i ) = f ′ ( x i ) ( x i + 1 − x i ) x i + 1 = x i − f ( x i ) f ′ ( x i ) \begin{aligned} 0-f(x_i) &=f'(x_i)(x_{i+1}-x_i) \\ x_{i+1}&=x_i-\frac{f(x_i)}{f'(x_i)} \end{aligned} 0f(xi)xi+1=f(xi)(xi+1xi)=xif(xi)f(xi)
对于这个符号,从直觉的角度理解,对于一个单调函数,如果f(x_i)和f’(x_i)要是同方向,就会离稳态越来越远,所以需要添加符号来保持稳态。使用简单的牛顿迭代法,参数会变化太大,所以在步长的选择上,有很多trick。
对于一个凸函数来说,梯度方向是让函数值升高的最快方向,对于一个非凸函数,梯度方向可能会导致求解进入局部最大值或者鞍点。
w ′ = w − λ f ′ ( x ) w ′ = w − λ β ∑ i ∈ β x ( i ) ( w T x ( i ) + b − y ( i ) ) b ′ = b − λ β ∑ i ∈ β ( w T x ( i ) + b − y ( i ) ) \begin{aligned} w' &=w-\lambda f'(x) \\ w' &= w-\frac{\lambda}{\beta}\sum_{i\in \beta}x^{(i)}(w^Tx^{(i)}+b -y^{(i)}) \\ b' & = b-\frac{\lambda}{\beta}\sum_{i\in \beta}(w^Tx^{(i)}+b -y^{(i)}) \\ \end{aligned} wwb=wλf(x)=wβλiβx(i)(wTx(i)+by(i))=bβλiβ(wTx(i)+by(i))

在这里插入图片描述

1.3 正态分布与平方损失

每个参数可能会有一定的噪声,噪声正态分布如下:
y = w ⃗ T x ⃗ + b + ϵ ϵ ∈ N ( 0 , σ 2 ) \begin{aligned} y &=\vec{w}^T\vec{x}+b+\epsilon \\ \epsilon& \in N(0, \sigma^2) \end{aligned} yϵ=w Tx +b+ϵN(0,σ2)

给定的x观察到特定的y的似然
p ( y ∣ x ) = 1 2 π σ 2 e x p ( − 1 2 σ 2 ( y − w ⃗ T x ⃗ − b ) 2 ) \begin{aligned} p(y|x)&=\frac{1}{\sqrt{2\pi \sigma^2}}exp(-\frac{1}{2\sigma^2}(y-\vec{w}^T\vec{x}-b)^2) \end{aligned} p(yx)=2πσ2 1exp(2σ21(yw Tx b)2)
每个点都是独立同分布
P ( y ∣ X ) = ∏ i = 1 n ( p ( y i ∣ x i ) ) P(y|X)=\prod_{i=1}^n(p(y^{i}|x^i)) P(yX)=i=1n(p(yixi))
进行对数
− l o g P ( y ∣ X ) = ∑ i = 1 n 0.5 l o g ( 2 π σ 2 ) + 1 2 σ 2 ( y i − w T x i − b ) 2 -logP(y|X)=\sum_{i=1}^n0.5log(2\pi \sigma^2)+\frac{1}{2\sigma^2}(y^i-w^Tx^i-b)^2 logP(yX)=i=1n0.5log(2πσ2)+2σ21(yiwTxib)2

2 线性回归从零开始实现

2.1 生成数据

def generate_data(w, b, num_examples):x = torch.norm(0, 1, (num_examples, len(w)))y = torch.matmul(w, x) + by += torch.norm(0, 0.01, y.shape())return x, y.reshape((-1, 1))

2.2 batch size data selector

def data_iter(features, labels, batch_size=10):num_examples = len(features)indices = list(range(num_examples))random.shuffle(indices)for i in range(0, num_examples, batch_size):batch_indices = torch.tensor(indices[i:min(i + batch_size, num_examples)])yield(features[batch_indices], labels[batch_indices]

2.3 定义网络和loss

sgd 和优化中的方法的区别,sgd利用部分样本,采用迭代的方式,进行优化;传统的优化方法,如qp或者sqp则对全部的样本的loss进行迭代,并且迭代过程中,会同时优化步长;

def linreg(x, w, b):y = torch.matmul(x, w) + breturn ydef loss(y_hat, y):l = 0.5 * (y - y_hat) ** 2return lw = torch.normal(0, 0.1, size=(2,1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)
def sgd(params, lr, batch_size):with torch.no_grad():for param in params:param -= lr * param.grad / batch_sizeparam.grad.zero_()

一定要在参数更新这里将param.grad.zero_()

2.4 进行训练

num_epochs = 3
net = linreg
lr = 0.02
batch_size = 10
for epoch in range(num_epochs):for x, y in data_iter(features, labels, batch_size):l = loss(y, net(x, w, b))l.sum().backward()sgd([w, b], lr, batch_size) with torch.no_grad():predicted = net(features, w, b)mse = ((predicted - labels) ** 2).mean()print("epoch ", epoch, " MSE: ", mse.item())

3 使用pytorch进行简化

3.1 数据选择器

# 定义迭代器
def data_selector(data_arrays, batch_size, is_train=True):dataset = data.TensorDataset(*data_arrays)return data.DataLoader(dataset, batch_size, shuffle=is_train)batch_size = 10
data_iter = data_selector((features, labels), batch_size, True)

3.2 网络

# 定义各种函数
from torch import nn
net = nn.Sequential(nn.Linear(2, 1))
# 初始化数值
net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)
# 定义损失函数
loss = nn.MSELoss()
# 使用优化算法
trainer = torch.optim.SGD(net.parameters(), lr=0.03)

采用框架,参数被封装在了net中,在定义sgd训练,使用net.parameters()传递参数

3.3 训练

num_epochs = 3
for epoch in range(num_epochs):for x, y in data_iter:l = loss(net(x), y)trainer.zero_grad()l.sum().backward()trainer.step()l = loss(net(x), y)print(f'epoch {epoch}, loss {l: f}')

4 softmax

在这里插入图片描述
我们在机器学习中经常会遇到分类问题,每个种类都自己的预测结果。
o ⃗ = W ⃗ x ⃗ + b ⃗ \vec{o}=\vec{W}\vec{x}+\vec{b} o =W x +b

4.1 softmax运算

如果只是这样简单的全连接层计算,会产生一个问题,输出的累计和并不等于1。但是我们的标签的总和是1.
为了让总和为1,每项的输出范围为[0,1],并且使用exp求导的时候更加简单
s o f t m a x ( x ) = e x p ( o ⃗ i ) ∑ i = 0 n ( e x p ( o ⃗ i ) ) softmax(x)=\frac{exp(\vec{o}_i)}{\sum_{i=0}^n(exp(\vec{o}_i))} softmax(x)=i=0n(exp(o i))exp(o i)
我们在做决策的时候,输出最大概率项
在这里插入图片描述

4.2 损失函数

使用最大似然估计
− l o g P ( Y ∣ X ) = ∑ i = 1 n − l o g P ( y ( i ) ∣ x ( i ) ) = ∑ i = 1 n l ( y ( i ) , y ^ ( i ) ) -logP(Y|X)=\sum_{i=1}^n-logP(y^{(i)}|x^{(i)})=\sum_{i=1}^nl(y^{(i)},\hat{y}^{(i)}) logP(YX)=i=1nlogP(y(i)x(i))=i=1nl(y(i),y^(i))
理解不了,以后再说。


  • 知道真实概率的人所经历的惊异程度
    H [ P ] = ∑ j − P ( j ) l o g P ( j ) H[P]=\sum_j-P(j)logP(j) H[P]=jP(j)logP(j)

4.3 训练代码

  • 数据
# 使用pytorchvision 下载数据
# iterator
trans = transforms.ToTensor()
mnist_train = torchvision.datasets.FashionMNIST(root="../data", train=True, transform=trans, download=True)
mnist_test = torchvision.datasets.FashionMNIST(root="../data", train=False, transform=trans, download=True)image, label = mnist_train[0]train_iter = data.DataLoader(mnist_train, 32, shuffle=True,num_workers=4)
test_iter = data.DataLoader(mnist_test, 32, shuffle=True,num_workers=4)
for x, y in train_iter:break
  • 定义网络结构
    这里要注意,pytorch上,采用nnum_inputs这种输入结构,输出结构1num_outputs
# 定义网络结构,输入结构是o=W*x+b, x是[n * 784], w = 784 * 10, b = 1 * 10
num_inputs = 784
num_outputs = 10
w = torch.normal(0, 0.01, (num_inputs, num_outputs), requires_grad=True)
b = torch.zeros(num_outputs, requires_grad=True)
print(w.shape, b.shape)
  • 定义softmax函数
# 定义关键函数softmax, 两个样本
x = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
y = torch.tensor([0, 2])
print(x[[0, 1], y])
# -log,这里的keepdim非常关键,这样才能保证两个数组的维度相同,可以对应上
def softmax(x):x_exp = torch.exp(x)partition = x_exp.sum(axis=1, keepdim=True)
#     print(partition.shape)return x_exp / partitionp_x = softmax(x)
print(p_x)
  • 定义loss
# 自定义模型
# 这里需要对x进行reshape,因为x很可能是乱的,需要reshape成n*num_inputs这种类型的
def net(x):return softmax(torch.matmul(x.reshape((-1, w.shape[0])), w) + b)# 定义损失函数
# 这里采用了小技巧,二维数组中,使用两个等长的向量,可以快捷的索引元素
def crossEntropy(y_hat, y):return -torch.log(y_hat[range(len(y_hat)), y])y = torch.tensor([0, 2])
y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
crossEntropy(y_hat, y)
  • 评估训练中的精度
# 记录分类精度, 用argmax(y_hat)==y, 记录是否正确
def accuracy(y_hat, y):# 防止y_hat采用概率, 并且有多个类别if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:y_hat = y_hat.argmax(axis=1)cmp = y_hat.type(y.dtype) == yreturn float(cmp.type(y.dtype).sum())# 用总数和预测值进行比较
accuracy(y_hat, y) / len(y)#创建一个通用的评估器
class Accumulator:def __init__(self, n):self.data = [0.0] * n# 解决各种不同类型元素累加的trickdef add(self, *args):self.data = [a + float(b) for a, b in zip(self.data, args)]def reset(self):self.data = [0.0] * len(self.data)def __getitem__(self, i):return self.data[i]def evaluate_accuracy(net, data_iter):if isinstance(net, torch.nn.Module):net.eval()  # 将模型设置为评估模式metrics = Accumulator(2)with torch.no_grad():for x, y in data_iter:metrics.add(accuracy(net(x), y), y.numel())return metrics[0] / metrics[1]evaluate_accuracy(net, test_iter)
  • 进行训练
#进行训练
lr = 0.1
def updater(batch_size):return d2l.sgd((w, b), lr, batch_size)def train_epoch_ch3(net, train_iter, loss, updater):if isinstance(net, torch.nn.Module):net.train()metric = Accumulator(3)for x, y in train_iter:y_hat = net(x)l = loss(y_hat, y)if isinstance(updater, torch.optim.Optimizer):updater.zero_grad()l.mean().backward()updater.step()else:l.sum().backward()updater(x.shape[0])metric.add(l.sum(), accuracy(y_hat, y), y.numel())return metric[0] / metric[2], metric[1] / metric[2]
  • 其他内容
class Animator:  #@save"""在动画中绘制数据"""def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,ylim=None, xscale='linear', yscale='linear',fmts=('-', 'm--', 'g-.', 'r:'), nrows=1, ncols=1,figsize=(3.5, 2.5)):# 增量地绘制多条线if legend is None:legend = []d2l.use_svg_display()self.fig, self.axes = d2l.plt.subplots(nrows, ncols, figsize=figsize)if nrows * ncols == 1:self.axes = [self.axes, ]# 使用lambda函数捕获参数self.config_axes = lambda: d2l.set_axes(self.axes[0], xlabel, ylabel, xlim, ylim, xscale, yscale, legend)self.X, self.Y, self.fmts = None, None, fmtsdef add(self, x, y):# 向图表中添加多个数据点if not hasattr(y, "__len__"):y = [y]n = len(y)if not hasattr(x, "__len__"):x = [x] * nif not self.X:self.X = [[] for _ in range(n)]if not self.Y:self.Y = [[] for _ in range(n)]for i, (a, b) in enumerate(zip(x, y)):if a is not None and b is not None:self.X[i].append(a)self.Y[i].append(b)self.axes[0].cla()for x, y, fmt in zip(self.X, self.Y, self.fmts):self.axes[0].plot(x, y, fmt)self.config_axes()display.display(self.fig)display.clear_output(wait=True)
  • 进行训练
def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater):  #@save"""训练模型(定义见第3章)"""animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],legend=['train loss', 'train acc', 'test acc'])for epoch in range(num_epochs):train_metrics = train_epoch_ch3(net, train_iter, loss, updater)test_acc = evaluate_accuracy(net, test_iter)animator.add(epoch + 1, train_metrics + (test_acc,))train_loss, train_acc = train_metricsassert train_loss < 0.5, train_lossassert train_acc <= 1 and train_acc > 0.7, train_accassert test_acc <= 1 and test_acc > 0.7, test_accnum_epochs = 10
train_ch3(net, train_iter, test_iter, crossEntropy, num_epochs, updater)

4.4 softmax 的简洁实现

通过softmax 函数得到每项的概率时
y ^ j = e x p ( o j ) ∑ k e x p ( o k ) \hat{y}_j=\frac{exp(o_j)}{\sum_kexp(o_k)} y^j=kexp(ok)exp(oj)
为了避免太大的数,造成数据的上溢,将特别大的项减掉
y ^ j = e x p ( o j − m a x ( o k ) ) ∑ k e x p ( o k − m a x ( o k ) ) \hat{y}_j=\frac{exp(o_j - max(o_k))}{\sum_kexp(o_k-max(o_k))} y^j=kexp(okmax(ok))exp(ojmax(ok))
这样会造成某一些数会非常小,接近0,在计算交叉熵时, y i l o g y ^ i y_ilog\hat{y}_i yilogy^i会出现无穷小的情况,计算交叉熵时有一个小技巧
l o g ( y ^ i ) = o j − m a x ( o k ) − l o g ( ∑ k e x p ( o k − m a x ( o k ) ) ) log(\hat{y}_i)=o_j-max(o_k)-log(\sum_kexp(o_k-max(o_k))) log(y^i)=ojmax(ok)log(kexp(okmax(ok)))

使用pytorch 完整的代码实现

import torch
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoadertransform = transforms.ToTensor()
train_dataset = torchvision.datasets.MNIST(root='./data', train=True, transform=transform, download=True)
test_dataset = torchvision.datasets.MNIST(root='./data', train=False, transform=transform)batch_size = 256
train_iter = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_iter = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)net = nn.Sequential(nn.Flatten(), nn.Linear(784, 10))
loss = nn.CrossEntropyLoss(reduction='mean')
trainer = torch.optim.SGD(net.parameters(), lr=0.03)
num_epochs = 10for epoch in range(num_epochs):total_loss = 0.0  # 初始化总损失为零for x, y in train_iter:# 前向传播output = net(x)l = loss(output, y)# 反向传播trainer.zero_grad()l.backward()trainer.step()# 累加批次的损失total_loss += l.item()  # 使用 l.item() 将损失转换为 Python 数字# 计算整个 epoch 的平均损失average_loss = total_loss / len(train_iter)# 打印当前轮的平均损失print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {average_loss:.4f}')
Epoch [1/10], Loss: 1.0835
Epoch [2/10], Loss: 0.6061
Epoch [3/10], Loss: 0.5108
Epoch [4/10], Loss: 0.4644
Epoch [5/10], Loss: 0.4364
Epoch [6/10], Loss: 0.4164
Epoch [7/10], Loss: 0.4017
Epoch [8/10], Loss: 0.3903
Epoch [9/10], Loss: 0.3814
Epoch [10/10], Loss: 0.3728

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

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

相关文章

2023机器人行业总结,2024机器人崛起元年(具身智能)

2023总结&#xff1a; 1.Chatgpt引爆了通用人工智能&#xff0c;最大的受益者或是机器人&#xff0c;2023年最热门的创业赛道便是人形机器人&#xff0c;优必选更是成为人形机器人上市第一股&#xff0c; 可以说2023年是机器人开启智能化的元年&#xff0c;而2024则将成为机器…

go执行静态二进制文件和执行动态库文件

目的和需求&#xff1a;部分go的核心文件不开源&#xff0c;例如验证&#xff0c;主程序核心逻辑等等 第一个想法&#xff0c;把子程序代码打包成静态文件&#xff0c;然后主程序执行 子程序 package mainimport ("fmt""github.com/gogf/gf/v2/os/gfile"…

[笔记] 使用 qemu 创建虚拟磁盘并安装 grub

之前使用 wsl 进行了直接创建虚拟磁盘并安装 grub,现在希望能够直接借助 qemu 的工具创建虚拟磁盘文件并安装 grub,由于需要用到 nbd(net block device网络块设备) 模块,在 wsl 中并不支持,因此这里使用到了 Hypver-V 虚拟机创建了一个 Ubuntu 系统,在系统中安装了 qemu 和 gru…

Spring Cloud Gateway + Nacos 实现动态路由

1、maven 依赖 主要依赖 <!-- 网关 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>案件差不多完整主要依赖 <!--Spring boot 依赖(微服务基…

uni-app 前后端调用实例 基于Springboot 详情页实现

锋哥原创的uni-app视频教程&#xff1a; 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中...共计23条视频&#xff0c;包括&#xff1a;第1讲 uni…

分布微服软件体系快速云端架构

1 概述 分布微服软件体系云端架构平台&#xff0c;以主流的NACOS服务器作为注册配置中心&#xff0c;采用主流的Gradle框架&#xff0c;内嵌Tomcat10以上版本&#xff0c;用于快速构造各类基于JDK17以上的信息应用系统的分布式微服务软件体系架构&#xff0c;可以适用关系型SQ…

k8s的网络

k8s的网络 k8s中的通信模式&#xff1a; 1、pod内部之间容器与容器之间的通信 在同一个pod中的容器共享资源和网络&#xff0c;使用同一个网络命名空间&#xff0c;可以直接通信的 2、同一个node节点之内&#xff0c;不同pod之间的通信 每个pod都有一个全局的真实的ip地址…

缓存cache和缓冲buffer的区别

目录 缓存&#xff08;cache&#xff09; 浏览器缓存 内存缓存 redis 缓冲&#xff08;buffer&#xff09; java 实现 BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter 数据库中的 join buffer 总结 近期被这两个词汇困扰了&#xff0c;感…

SQL中 Group by Grouping Sets 分组的用法

文章目录 1. 用法2. 语法3. 实际应用3.1 求总和与小计3.2 按多个维度分组3.3 标记小计和总计 1. 用法 将Grouping Sets 运算符添加到Group by 子句中&#xff0c;使用Grouping Set 可以在一个查询中指定数据的多个分组&#xff0c;其结果与针对指定的组执行union all 运算等效…

玩机技巧|电脑下方的任务栏卡死如何解决

你是否遇到过&#xff0c;电脑下方的任务栏点不动&#xff0c;开始菜单点击了都没有反应的情况。你是否还在强制性关机&#xff08;按电源&#xff09;的解决这个问题。废话不多说&#xff0c;上干货 首先点击键盘上的ctrlshiftesc键&#xff0c;弹出任务管理器&#xff0c;如…

Java 第19章 IO流 课堂练习+本章作业

文章目录 Buffered流拷贝二进制文件创建文件写入文本读取文本文件存读Properties文件 Buffered流拷贝二进制文件 package com.hspedu.chapter19.outputStream;import java.io.*;public class BufferedCopy02 {public static void main(String[] args) {String srcFilePath &q…

大创项目推荐 深度学习人脸表情识别算法 - opencv python 机器视觉

文章目录 0 前言1 技术介绍1.1 技术概括1.2 目前表情识别实现技术 2 实现效果3 深度学习表情识别实现过程3.1 网络架构3.2 数据3.3 实现流程3.4 部分实现代码 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习人脸表情识别系…

redis 三主六从高可用dockerswarm高级版(不固定ip)

redis集群(cluster)笔记 redis 三主三从高可用集群docker swarm redis 三主六从高可用docker(不固定ip) redis 三主六从高可用dockerswarm高级版(不固定ip) 此博客解决&#xff0c;redis加入集群后&#xff0c;是用于停掉后重启&#xff0c;将nodes.conf中的旧的Ip替换为新的…

docker搭建Dinky —— 筑梦之路

简介 Dinky 是一个 开箱即用 、易扩展 &#xff0c;以 Apache Flink 为基础&#xff0c;连接 OLAP 和 数据湖 等众多框架的 一站式 实时计算平台&#xff0c;致力于 流批一体 和 湖仓一体 的探索与实践。 主要功能 其主要功能如下&#xff1a; 沉浸式 FlinkSQL 数据开发&#x…

PHP开发日志 ━━ 基于PHP和JS的AES相互加密解密方法详解(CryptoJS) 适合CryptoJS4.0和PHP8.0

最近客户在做安全等保&#xff0c;需要后台登录密码采用加密方式&#xff0c;原来用个base64变形一下就算了&#xff0c;现在不行&#xff0c;一定要加密加key加盐~~ 前端使用Cypto-JS加密&#xff0c;传输给后端使用PHP解密&#xff0c;当然&#xff0c;前端虽然有key有盐&…

书生-浦路大模型全链路开源体系

2023年&#xff0c;大模型成为热门关键词 论文链接 大模型已经成为发展通用人工智能的重要途经 模型评测过程&#xff1a;从模型到应用 全链条开源开发体系 | 数据&#xff1a; 多模态融合 万卷包含文本、图像和视频等多模态数据&#xff0c;涵盖科技、文学、媒体、教育和法…

奋楫扬帆,奔赴新程 | 2023 年图扑大事记回顾,与您携手共迎 2024

2023.01 工信部公示了 2022 年度智能制造示范工厂揭榜单位和优秀场景名单。图扑软件和上海洲邦合作建设的宁波甬友数字孪生工厂被评为优秀场景&#xff0c;全国共有 369 个智能制造典型场景入选。 2023.01 在第十一届中国创新创业大赛全国赛&#xff08;新一代信息技术&#…

react+redux+antd-mobile 之 记账本案例

1.环境搭建 //使用CRA创建项目&#xff0c;并安装必要依赖&#xff0c;包括下列基础包 //1. Redux状态管理 - reduxjs/toolkit 、 react-redux //2. 路由 - react-router-dom //3. 时间处理 - dayjs //4. class类名处理 - classnames //5. 移动端组件库 - antd-mobile //6. 请…

SAP badi增强查找

查找SAP BADI的方法. 1. 通过SE24 查找. 输入 CL_EXITHANDLER, 双击 GET_INTANCE. 设定断点. 执行Tcode, 当有出口时, 程式会自动进入Debug界面. 观察 EXIT_NAME的值. 2. 同样可能SE80中通过Package查找. 3. 通过ST05 追踪, BADI对应的数据表为 SXS_INTER, SXC_EXIT, SXC…

报告解读:中国新一代终端安全市场洞察,2023

报告解读 中国新一代终端安全市场洞察 2023 安全防御的“最前线” 01 混沌的企业安全 以下来自CSO们最关注的安全热点问题&#xff1a; Q1我们如何看待当下泛化的终端安全&#xff0c;混合的IT环境企业面临的安全变化&#xff1f; IDC&#xff1a;伴随着全球数字化转型的快…