pytorch 实现线性回归 softmax(Pytorch 04)

一 softmax 定义

softmax 是多分类问题,对决策结果不是多少,而是分类,哪一个。

为了估计所有可能类别的条件概率,我们需要一个有 多个输出的模型,每个类别对应一个输出。为了解决线 性模型的分类问题,我们需要和输出一样多的仿射函数(affine function)。每个输出对应于它自己的仿射函数。在我们的例子中,由于我们有 4个特征和3个可能的输出类别,我们将需要12个标量来表示权重(带下标 的w),3个标量来表示偏置(带下标的b)。

与线性回归一样,softmax回归也是一个 单层神经网络。 由于计算每个输出o1、o2和o3取决于所有输入x1、x2、x3和x4,所以softmax回归的 输出层也是全连接层

现在我们将优化参数以最大化观测数据的概率。为了得到预测结果,我们将设置一个阈值,如 选择具有最大概率的标签

要将输出视为概率,我们必须 保证在任何数据上的输出都是非负的且总和为1。此外,我们需要一个训练的目标函数,来激励模型精准地估计概率。

尽管softmax是一个非线性函数,但softmax回归的输出仍然由输入特征的仿射变换决定。因此,softmax回归是一个线性模型(linear model)。

1.1 交叉熵损失:

导数是我们softmax模型分配的概率与实际发生的情况(由独热标签向量表示)之间的差异。从 这个意义上讲,这与我们在回归中看到的非常相似,其中 梯度是观测值y和估计值yˆ之间的差异。这不是巧合, 在任何指数族分布模型中,对数似然的梯度正是由此得出的。这使 梯度计算在实践中变得容易很多。对于标签y,我们可以使用与以前相 同的表示形式。唯一的区别是,我们现在用一个 概率向量 表示,如(0.1, 0.2, 0.7),而不是仅包含二元项的向 量(0, 0, 1)。我们使用下公式来定义损失l,它是所有标签分布的预期损失值。此损失称为交叉熵损失(cross‐ entropy loss),它是分类问题最常用的损失之一。

1.2 模型预测和评估

在训练softmax回归模型后,给出任何样本特征,我们可以 预测每个输出类别的概率。通常我们 使用预测概率最高的类别作为输出类别。如果预测与实际类别(标签)一致,则预测是正确的。在接下来的实验中,我 们将使用精度(accuracy)来评估模型的性能。精度等于正确预测数与预测总数之间的比率。

  • softmax运算获取一个向量并将其映射为概率。
  • softmax回归适用于分类问题,它使用了softmax运算中输出类别的概率分布。

二 MNIST数据集 导入

Fashion‐MNIST由 10个类别的图像 组成,每个类别由训练数据集(train dataset)中的6000张图像和测试数据 集(test dataset)中的1000张图像组成。

%matplotlib inline
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2l
d2l.use_svg_display()
# 通过ToTensor实例将图像数据从PIL类型变换成32位浮点数格式,
# 并除以255使得所有像素的数值均在0~1之间
trans = transforms.ToTensor()  # download=True
mnist_train = torchvision.datasets.FashionMNIST(root="../data", train=True, 
                                                transform=trans, download=False)
mnist_test = torchvision.datasets.FashionMNIST(root="../data", train=False, 
                                               transform=trans, download=False)
len(mnist_train), len(mnist_test)
# (60000, 10000)

每个输入图像的高度和宽度均为28像素。数据集由灰度图像组成,其通道数为1。

mnist_train[0][0].shape
# torch.Size([1, 28, 28])

Fashion‐MNIST中包含的10个类别,分别为 t‐shirt(T恤)、trouser(裤子)、pullover(套衫)、dress(连衣 裙)、coat(外套)、sandal(凉鞋)、shirt(衬衫)、sneaker(运动鞋)、bag(包)和ankle boot(短靴)

def get_fashion_mnist_labels(labels): #@save
    """返回Fashion-MNIST数据集的文本标签"""
    text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
    'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
    return [text_labels[int(i)] for i in labels]

def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5): #@save
    """绘制图像列表"""
    figsize = (num_cols * scale, num_rows * scale)
    _, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize)
    axes = axes.flatten()
    for i, (ax, img) in enumerate(zip(axes, imgs)):
        if torch.is_tensor(img):
            # 图片张量
            ax.imshow(img.numpy())
        else:
            # PIL图片
            ax.imshow(img)
        ax.axes.get_xaxis().set_visible(False)
        ax.axes.get_yaxis().set_visible(False)
        if titles:
            ax.set_title(titles[i])
    return axes

X, y = next(iter(data.DataLoader(mnist_train, batch_size=18)))
show_images(X.reshape(18, 28, 28), 2, 9, titles=get_fashion_mnist_labels(y));

 

 三 从零开始实现 softmax

3.1 读取 MNIST数据集

def get_dataloader_workers(): #@save
    """使用4个进程来读取数据"""
    return 4

def load_data_fashion_mnist(batch_size, resize=None): #@save
    """下载Fashion-MNIST数据集,然后将其加载到内存中"""
    trans = [transforms.ToTensor()]
    if resize:
        trans.insert(0, transforms.Resize(resize))
    trans = transforms.Compose(trans)
    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)
    return (data.DataLoader(mnist_train, batch_size, shuffle=True,
                            num_workers=get_dataloader_workers()),
            data.DataLoader(mnist_test, batch_size, shuffle=False,
                            num_workers=get_dataloader_workers()))
import torch
from IPython import display
from d2l import torch as d2l

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
train_iter, test_iter 

# (<torch.utils.data.dataloader.DataLoader at 0x27e6143bd30>,
#  <torch.utils.data.dataloader.DataLoader at 0x27e61e1a970>)

3.2 初始化模型参数

num_inputs = 784
num_outputs = 10
W = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)
b = torch.zeros(num_outputs, requires_grad=True)
W, b

# (tensor([[ 7.8446e-03,  3.8895e-04,  7.4652e-03,  ...,  7.9335e-03,
#           -2.6370e-02, -3.4869e-03],
#          [ 1.1907e-02, -1.7130e-03, -5.7840e-04,  ...,  1.7916e-04,
#           -5.7439e-03,  9.6542e-03],
#          [ 3.0170e-02, -1.4055e-02,  1.8777e-02,  ...,  8.5911e-03,
#            4.6043e-03,  3.0010e-03],
#          ...,
#          [-1.2875e-03, -8.0845e-03, -3.4810e-02,  ...,  1.0136e-02,
#           -1.7731e-02,  3.4934e-03],
#          [-3.7752e-03, -6.9249e-03,  9.0967e-04,  ...,  1.6938e-02,
#            1.4804e-02,  8.6243e-03],
#          [ 1.7685e-02, -6.8463e-03, -4.2527e-05,  ...,  5.0289e-03,
#           -9.5934e-03, -6.3647e-03]], requires_grad=True),
#  tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], requires_grad=True))

3.3 定义softmax操作

给定一个矩阵X,我们可以对所有元素求和(默认情况下)。也可以 只求同一个轴上的元素,即 同一列(轴0)或同一行(轴1)。如果X是一个形状为(2, 3)的张量,我们 对列进行求和,则结果将是一个具 有形状(3,)的向量。当调用sum运算符时,我们可以指定保持在原始张量的轴数,而不折叠求和的维度。这将 产生一个具有形状(1, 3)的二维张量。

X = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
X.sum(0, keepdim=True), X.sum(1, keepdim=True)

# (tensor([[5., 7., 9.]]),
#  tensor([[ 6.],
#          [15.]]))

3.4 定义模型

定义了输入如何通过网络映射到输出。注 意,将数据传递到模型之前,我们使用 reshape 函数将每张原始图像 展平为向量

def softmax(X):
    X_exp = torch.exp(X)
    partition = X_exp.sum(1, keepdim=True)
    return X_exp / partition # 这里应用了广播机制
X = torch.normal(0, 1, (2, 5))
X_prob = softmax(X)
X_prob, X_prob.sum(1)

# (tensor([[0.0589, 0.1685, 0.4852, 0.0695, 0.2180],
#          [0.7117, 0.0458, 0.0469, 0.1268, 0.0688]]),
#  tensor([1., 1.]))
def net(X):
    return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)

 

3.5 定义损失

实现引入的 交叉熵损失函数。这可能是深度学习中 最常见的损失函数,因为目前 分类问题的数量远远超过回归问题的数量。 回顾一下,交叉熵采用真实标签的预测概率的负对数似然。

y = torch.tensor([0, 2])
y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
y_hat[[0, 1], y]

# tensor([0.1000, 0.5000])
def cross_entropy(y_hat, y):
    return - torch.log(y_hat[range(len(y_hat)), y])
cross_entropy(y_hat, y)   

# tensor([2.3026, 0.6931])

给定预测概率分布y_hat,当我们必须输出硬预测(hard prediction)时,我们 通常选择预测概率最高的类。 许多应用都要求我们做出选择。如Gmail必须将电子邮件分类为“Primary(主要邮件)”、“Social(社交邮 件)”“Updates(更新邮件)”或“Forums(论坛邮件)”。Gmail做分类时可能在内部估计概率,但最终它必 须在类中选择一个。

当 预测与标签分类y一致时,即是正确的。分类精度即正确预测数量与总预测数量之比。

为了计算精度,我们执行以下操作。首先,如果y_hat是矩阵,那么假定第二个维度存储每个类的预测分数。 我们使用argmax获得每行中最大元素的索引来获得预测类别。然后我们将预测类别与真实y元素进行比较。由 于等式运算符“==”对数据类型很敏感,因此我们 将 y_hat 的数据类型转换为与y的数据类型一致。结果是一 个包含0(错)和1(对)的张量

def accuracy(y_hat, y): #@save
    """计算预测正确的数量"""
    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) == y
    return float(cmp.type(y.dtype).sum())
accuracy(y_hat, y) / len(y)
# 0.5

对于任意 数据迭代器 data_iter 可访问的数据集,我们可以评估在任意模型net的精度。

def evaluate_accuracy(net, data_iter): #@save
    """计算在指定数据集上模型的精度"""
    if isinstance(net, torch.nn.Module):
        net.eval() # 将模型设置为评估模式
    metric = Accumulator(2) # 正确预测数、预测总数
    with torch.no_grad():
        for X, y in data_iter:
            metric.add(accuracy(net(X), y), y.numel())
    return metric[0] / metric[1]

这里定义一个实用程序类Accumulator,用于 对多个变量进行累加。在上面的evaluate_accuracy函数中,我 们在Accumulator实例中创建了2个变量,分别用于 存储正确预测的数量和预测的总数量。当我们遍历数据集 时,两者都将随着时间的推移而累加。

class Accumulator: #@save
    """在n个变量上累加"""
    def __init__(self, n):
        self.data = [0.0] * n
    def 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, idx):
        return self.data[idx]

由于我们使用随机权重初始化net模型,因此该模型的精度应接近于随机猜测。例如在 有10个类别情况下的 精度为0.1

evaluate_accuracy(net, test_iter)
# 0.1045

3.6 执行训练

def train_epoch_ch3(net, train_iter, loss, updater): #@save
    """训练模型一个迭代周期(定义见第3章)"""
    # 将模型设置为训练模式
    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):
            # 使用PyTorch内置的优化器和损失函数
            updater.zero_grad()
            l.mean().backward()
            updater.step()
        else:
            # 使用定制的优化器和损失函数
            l.sum().backward()
            updater(X.shape[0])
        metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())
    # 返回训练损失和训练精度
    return metric[0] / metric[2], metric[1] / metric[2]

在展示训练函数的实现之前,我们定义一个在 动画中绘制 数据的实用程序类Animator:

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, fmts
        
    def add(self, x, y):
        # 向图表中添加多个数据点
        if not hasattr(y, "__len__"):
            y = [y]
        n = len(y)
        if not hasattr(x, "__len__"):
            x = [x] * n
        if 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)

接下来我们实现一个训练函数,它会在 train_iter访问到的训练数据集上训练一个模型net。该训练函数将 会运行多个迭代周期(由num_epochs指定)。在每个迭代周期结束时,利用test_iter访问到的测试数据集对 模型进行评估。我们将利用Animator类来可视化训练进度。

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_metrics
    assert train_loss < 0.5, train_loss
    assert train_acc <= 1 and train_acc > 0.7, train_acc
    assert test_acc <= 1 and test_acc > 0.7, test_acc

作为一个从零开始的实现,我们使用定义的 小批量随机梯度下降 来优化模型的损失函数,设置学习 率为0.1。

lr = 0.1
def updater(batch_size):
    return d2l.sgd([W, b], lr, batch_size)

我们训练模型 10个迭代周期迭代周期(num_epochs)和学习率(lr)都是可调节的超参数。 通过更改它们的值,我们可以提高模型的分类精度。

num_epochs = 10
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)

3.7 执行训练

def predict_ch3(net, test_iter, n=6): #@save
    """预测标签(定义见第3章)"""
    for X, y in test_iter:
        break
    trues = d2l.get_fashion_mnist_labels(y)
    preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))
    titles = [true +'\n' + pred for true, pred in zip(trues, preds)]
    d2l.show_images( X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])
    
predict_ch3(net, test_iter)

训练过程:先读取数据,再定义模型和损失函数,然后 使用优化算法训练模型。大多数常见的深度学习模型都有类似的训练过程。

四 导包实现

import torch
from torch import nn
from d2l import torch as d2l

 读取数据集:

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
len(train_iter), len(test_iter)
# (235, 40)

初始化权重:

# PyTorch不会隐式地调整输入的形状。因此,
# 我们在线性层前定义了展平层(flatten),来调整网络输入的形状
net = nn.Sequential(nn.Flatten(), nn.Linear(784, 10))
def init_weights(m):
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight, std=0.01)
net.apply(init_weights)

# Sequential(
#   (0): Flatten(start_dim=1, end_dim=-1)
#   (1): Linear(in_features=784, out_features=10, bias=True)
# )

定义 交叉熵损失损失:

loss = nn.CrossEntropyLoss(reduction='none')
loss

# CrossEntropyLoss()

梯度转换:

trainer = torch.optim.SGD(net.parameters(), lr = 0.1)
trainer

# SGD (
# Parameter Group 0
#     dampening: 0
#     differentiable: False
#     foreach: None
#     lr: 0.1
#     maximize: False
#     momentum: 0
#     nesterov: False
#     weight_decay: 0
# )

执行训练:

num_epochs = 10
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux cp、mv命令显示进度条

1.advcpmv 平常使用cp 拷贝大文件时&#xff0c;看不到多久可以完成&#xff0c;虽然加上-v参数也只能看到正在拷贝文件&#xff0c;那就使用以下方法实现 git clone https://github.com/jarun/advcpmv.git cd advcpmv/ bash install.shmv ./advcp /usr/local/bin/ mv ./advmv …

【旅游景点项目日记 | 第二篇】基于Selenium爬取携程网景点详细数据

文章目录 3.基于Selenium爬取携程网景点详细数据3.1前提环境3.2思路3.3代码详讲3.3.1查询指定城市的所有景点3.3.2获取详细景点的访问路径3.3.3获取景点的详细信息 3.4数据库设计3.5全部代码3.6效果图 3.基于Selenium爬取携程网景点详细数据 3.1前提环境 确保安装python3.x环…

生产力工具|安装更新R软件(R、studio)

内容介绍&#xff1a; 安装R软件&#xff1a; 下载 R X64 3.5.1: 访问官方R网站 https://cran.r-project.org/。选择适合Windows版本的安装包。将安装包下载到您的计算机。 本地安装: 运行下载的“R-3.5.1-win.exe”文件。按照安装向导&#xff0c;选择安装路径&#xff0c;取消…

Windows 进程权限浅谈 -- 提权 / 降权

在 Windows 上&#xff0c;用户对权限并不敏感&#xff0c;可能最为直观的是 UAC &#xff0c;但相信很多人已经关掉了它的提示。 但其实安全性早已深入了 Windows 的方方面面。Windows Vista 引入了一个称为强制完整性控制&#xff08;Mandatory Integrity Controls&#xff0…

BMS设计中的短路保护和MOSFET选型(上)

电池管理系统&#xff08;BMS&#xff09;是一种能够对电池进行监控和管理的电子装备&#xff0c;是电池与用户之间的纽带。通过对电压、电流、温度以及SOC等数据采集&#xff0c;计算进而控制电池的充放电过程&#xff0c;主要就是为了能够提高电池的利用率&#xff0c;防止电…

【Python从入门到进阶】51、电影天堂网站多页面下载实战

接上篇《50、当当网Scrapy项目实战&#xff08;三&#xff09;》 上一篇我们讲解了使用Scrapy框架在当当网抓取多页书籍数据的效果&#xff0c;本篇我们来抓取电影天堂网站的数据&#xff0c;同样采用Scrapy框架多页面下载的模式来实现。 一、抓取需求 打开电影天堂网站&…

Ubuntu Desktop 更改默认应用程序 (Videos -> SMPlayer)

Ubuntu Desktop 更改默认应用程序 [Videos -> SMPlayer] References System Settings -> Details -> Default Applications 概况、默认应用程序、可移动介质、法律声明 默认应用程序&#xff0c;窗口右侧列出了网络、邮件、日历、音乐、视频、照片操作的默认应用程序…

OCR如何解决字体多样性难题?

OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;技术的确是一项非常实用的技术&#xff0c;能够将图像中的文字转化为可编辑的文本&#xff0c;大大提高了工作效率。然而&#xff0c;你所遇到的问题——字体多样性导致的模型泛化能力不足&a…

AtCoder Regular Contest 175(A~B)

补题&#xff1a;A - Spoon Taking Problem 阅读理解就能劝退好多人&#xff0c;先看B题可能收益会更高。 N个人都是这么坐的&#xff0c;勺子标号也给你标好了。 如果 s[1]L&#xff0c;那么1这个人就要拿左边的勺子&#xff0c;如果左边没有就拿右边的&#xff0c;右边也没…

[AutoSar]BSW_ OS CORE, Physical core,EcuC core,EcuC partition,OSApplication的关系

目录 关键词平台说明一、总体依赖关系二、相关概念三、在配置中的实现3.1 EcucPartition3.2 OsApplication3.3 Ecu core 关键词 嵌入式、C语言、autosar、OS、BSW 平台说明 项目ValueOSautosar OSautosar厂商vector &#xff0c; EB芯片厂商TI 英飞凌编程语言C&#xff0c;C…

Centos7 防火墙iptables?

Centos7 防火墙iptables&#xff1f; 文章目录 Centos7 防火墙iptables&#xff1f;1. 介绍2. firewalld 和 iptables区别3. 区域管理概念区域管理有如下几种不同的初始化区域&#xff1a; 4.iptables的配置1.简述2.基本原理3.iptables传输数据包的过程4. iptables规则表和链5.…

C++初阶:STL容器list的使用与初版自实现

目录 1. list的接口与使用1.1 默认成员函数1.2 迭代器与容量相关成员函数1.3 存储数据操作相关成员函数1.4 其他list操作成员函数 2. list的自实现2.1 list的自实现功能2.2 list的结点结构2.3 list的迭代器2.3 list的结构2.4 list迭代器的运算符重载2.5 list的成员函数 3. cons…

python绘图matplotlib——使用记录2

本博文来自于网络收集&#xff0c;如有侵权请联系删除 三维图绘制 1 三维散点图2 三维柱状图三维曲面 1 三维散点图 import matplotlib.pyplot as plt import numpy as npfrom mpl_toolkits.mplot3d import Axes3Dfig plt.figure() # ax fig.gca(projection"3d")…

javase day11笔记

第十一天课堂笔记 构造代码块 { } 给 所有对象 共性特点 进行初始化操作 创建对象时在堆区对象中存放实例变量,同时执行构造代码块 执行顺序:静态代码块—>非静态代码块—>构造方法 继承★★★ 将多个类中相同的实例变量和实例方法 , 单独存放到一个类中,成为父类…

【Linux】写个日志和再谈线程池

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;信号量和线程池 目录 &#x1f449;&#x1f3fb;日志代码Log.cppMain.cc &#x1f449;&#x1f3fb;线程池代码LockGuard.hpp(自定义互斥锁&#xff0c;进…

网易web安全工程师进阶版课程

课程介绍 《Web安全工程师&#xff08;进阶&#xff09;》是由“ i春秋学院联合网易安全部”出品&#xff0c;资深讲师团队通过精炼的教学内容、丰富的实际场景及综合项目实战&#xff0c;帮助学员纵向提升技能&#xff0c;横向拓宽视野&#xff0c;牢靠掌握Web安全工程师核心…

Python6:Socket编程初步学习笔记

Socket协议概要 创建socket的时候&#xff0c;需要一些选项来说明本次使用协议具体是什么&#xff0c;常用的两个&#xff1a; 由此产生的不同组合&#xff1a; 但目前TCP(IPV4)是主流&#xff0c;SOCK_STREAMAF_INET 创建和使用Socket socket模块中有socket类&#xff1a…

51单片机学习笔记——LED闪烁和流水灯

任务分析 首先要知道LED闪烁主要是怎么工作的&#xff0c;闪烁亮灭自然是一下为高一下为低&#xff0c;亮灭的频率则需要延时来进行控制。 上节已经知道了如何点亮那延时如何做呢首先先编写主框架 这样是否可以通过循环将LED灯一直循环闪烁。 以为while一直在循环所以其实是可…

向开发板上移植ip工具:交叉编译 ip工具

一. 简介 前面几篇文章学习了 CAN设备节点的创建&#xff0c;以及如何使能 CAN驱动。 本文学习向开发板上移植ip工具。 二. 向开发板上移植ip工具&#xff1a;交叉编译 ip工具 注意&#xff1a;在移植 ip 命令的时候必须先对根文件系统做个备份&#xff01;防止操作失误导…

力扣74---搜索二维矩阵

目录 题目描述&#xff1a; 思路&#xff1a; 代码&#xff1a; 题目描述&#xff1a; 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 targ…