二、线性神经网络

文章目录

  • 前言
  • 一、线性回归
    • 1. 线性回归的基本元素
      • 1.1 线性模型
      • 1.2 损失函数
      • 1.3 解析解
      • 1.4 梯度下降
      • 1.5 用模型进行预测
    • 2. 正态分布与平方损失
    • 3. 从线性回归到深度网络
  • 二、线性回归的代码实现
    • 1. 生成数据集
    • 2. 读取数据集
      • 2.1 手动实现读取数据集
      • 2.2 简洁实现读取数据集
    • 3. 初始化模型参数
      • 3.1 手动初始化
      • 3.2 简洁实现初始化
    • 4. 定义模型
      • 4.1 手动定义
      • 4.2 简洁定义
    • 5. 定义损失函数
      • 5.1 手动定义
      • 5.2 简洁定义
    • 6. 定义优化算法
      • 6.1 手动定义
      • 6.2 简洁定义
    • 7. 训练
      • 7.1 手动训练
      • 7.2 简洁训练
  • 三、逻辑回归
    • 3.1 二分类回归
      • 3.1.1 二分类回归的大致流程
      • 3.1.2 sigmoid函数
      • 3.1.3 定义损失函数
      • 3.1.4 手动代码实现
    • 3.2 多分类回归
      • 3.2.1 网络架构
      • 3.2.2 大致流程
      • 3.2.3 softmax函数
      • 3.2.4 损失函数
      • 3.2.5 避免softmax函数上溢以及对数下溢
      • 3.2.6 softmax回归代码实现
  • 总结


前言

在介绍深度神经网络之前,我们需要了解神经网络训练的基础知识。 本章我们将介绍神经网络的整个训练过程, 包括:定义简单的神经网络架构、数据处理、指定损失函数和如何训练模型。 为了更容易学习,我们将从经典算法————线性神经网络开始,介绍神经网络的基础知识。 经典统计学习技术中的线性回归和softmax回归可以视为线性神经网络, 这些知识将为其他部分中更复杂的技术奠定基础。

一、线性回归

1. 线性回归的基本元素

1.1 线性模型

这里先假设我们的模型是用来预测房屋价格的。设特征个数为2,分别为面积和房龄,目标是房屋价格,则可用下式表达:
p r i c e = w a r e a ⋅ a r e a + w a g e ⋅ a g e + b . \mathrm{price} = w_{\mathrm{area}} \cdot \mathrm{area} + w_{\mathrm{age}} \cdot \mathrm{age} + b. price=wareaarea+wageage+b.

其中w可称为权重,用来衡量每个特征对预测值的影响程度,b称为偏置项(或偏移量、截距),偏置项可以提高模型的表达能力。

数学表达:
y ^ = w 1 x 1 + . . . + w d x d + b . \hat{y} = w_1 x_1 + ... + w_d x_d + b. y^=w1x1+...+wdxd+b.

其中 y ^ \hat{y} y^ 表示预测值,w表示权重,x表示特征值,b表示偏置项。

上式向量表示:
y ^ = w ⊤ x + b . \hat{y} = \mathbf{w}^\top \mathbf{x} + b. y^=wx+b.

这是一个样本的表达式,因此这里的y是一个标量。

多个样本的表达式如下:
y ^ = X w + b {\hat{\mathbf{y}}} = \mathbf{X} \mathbf{w} + \mathbf{b} y^=Xw+b

其中 y ^ \hat{\mathbf{y}} y^与w是一个一维向量, X \mathbf{X} X是一个矩阵,b是一个标量,b可通过广播机制与Xw的结果每个元素相加。

注b是可以合并在w中的,具体如下图所示:

在这里插入图片描述

1.2 损失函数

使用平方误差公式 作为线性回归的损失函数:
l ( i ) ( w , b ) = 1 2 ( y ^ ( i ) − y ( i ) ) 2 . l^{(i)}(\mathbf{w}, b) = \frac{1}{2} \left(\hat{y}^{(i)} - y^{(i)}\right)^2. l(i)(w,b)=21(y^(i)y(i))2.

其中 i i i表示第 i i i个样本,因此所有样本的总损失函数可设为:
L ( w , b ) = 1 n ∑ i = 1 n l ( i ) ( w , b ) = 1 n ∑ i = 1 n 1 2 ( w ⊤ x ( i ) + b − y ( i ) ) 2 . L(\mathbf{w}, b) =\frac{1}{n}\sum_{i=1}^n l^{(i)}(\mathbf{w}, b) =\frac{1}{n} \sum_{i=1}^n \frac{1}{2}\left(\mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)}\right)^2. L(w,b)=n1i=1nl(i)(w,b)=n1i=1n21(wx(i)+by(i))2.

1.3 解析解

由于线性回归问题是一个很简单的优化问题,我们可以推出它的解析解,所谓解析解就是能用公式直接推出权重的值。
w ∗ = ( X ⊤ X ) − 1 X ⊤ y . \mathbf{w}^* = (\mathbf X^\top \mathbf X)^{-1}\mathbf X^\top \mathbf{y}. w=(XX)1Xy.

推导过程如下:
y = X w ⇒ X T y = X T X w ⇒ w = ( X T X ) − 1 X T y y = Xw\Rightarrow X^Ty = X^TXw\Rightarrow w = (X^TX)^{-1}X^Ty y=XwXTy=XTXww=(XTX)1XTy

1.4 梯度下降

即使我们无法得到解析解,我们也可以通过梯度下降方法来优化损失函数。

梯度是指向某个函数在每一点处上升最快的方向的向量,故其反向量指向函数下降最快的方向,因此我们可利用梯度下降来求得函数的最小值,该最小值不一定是全局最小值,但对于凸函数一定是全局最小值。

我们可使用如下公式来迭代的 x \mathbf{x} x:
x = x − l r ∗ ∂ L ( w ) ∂ w \mathbf{x} = \mathbf{x} - lr * \frac{\partial L(w)}{\partial w} x=xlrwL(w)

其中lr表示学习率,用来控制迭代的幅度。

根据求梯度的方式不同,梯度下降可分为如下几种:

  • 批量梯度下降: 即求梯度时,使用全部样本数据来求梯度。
    • 优点:全面优化,收敛快,可用向量并行计算
    • 缺点:开销大,更新慢,容易陷入局部最优解
  • 随机梯度下降: 随机选取一个样本进行梯度计算。
    • 优点:速度快,可跳出局部最优解
    • 缺点: 方向不稳定导致收敛的速度不确定,可能陷入噪声中,需要更多次迭代。
  • 小批量梯度下降: 使用一部分样本进行梯度的计算。是 前两个的折中,最常用。

1.5 用模型进行预测

根据上面的步骤后,我们已经求得模型,因此我们可以使用该模型进行预测新的房价,这种行为称为预测(prediction)–更准确 或者 推断(inference)

2. 正态分布与平方损失

为什么我们可以使用均方差 来表示线性回归的损失函数呢,这里涉及到正态分布 以及最大似然函数的计算.
P ( y ∣ X ) = ∏ i = 1 n p ( y ( i ) ∣ x ( i ) ) . P(\mathbf y \mid \mathbf X) = \prod_{i=1}^{n} p(y^{(i)}|\mathbf{x}^{(i)}). P(yX)=i=1np(y(i)x(i)).

− log ⁡ P ( y ∣ X ) = ∑ i = 1 n 1 2 log ⁡ ( 2 π σ 2 ) + 1 2 σ 2 ( y ( i ) − w ⊤ x ( i ) − b ) 2 . -\log P(\mathbf y \mid \mathbf X) = \sum_{i=1}^n \frac{1}{2} \log(2 \pi \sigma^2) + \frac{1}{2 \sigma^2} \left(y^{(i)} - \mathbf{w}^\top \mathbf{x}^{(i)} - b\right)^2. logP(yX)=i=1n21log(2πσ2)+2σ21(y(i)wx(i)b)2.

3. 从线性回归到深度网络

线性回归相当于单层的神经网络,图如下:
在这里插入图片描述

注:这是单层的

对于线性回归,每个输入都与每个输出(在本例中只有一个输出)相连, 我们将这种变换称为全连接层(fully-connected layer)或称为稠密层(dense layer)。

二、线性回归的代码实现

引入包:

%matplotlib inline
import random
import torch
from d2l import torch as d2l

1. 生成数据集

def synthetic_data(w, b, num_examples):  #@save
    """生成y=Xw+b+噪声"""
    X = torch.normal(0, 1, (num_examples, len(w)))
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape)  #加了噪声
    return X, y.reshape((-1, 1))  #返回数据集 以及标签

true_w = torch.tensor([2, -3.4]) 
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

2. 读取数据集

2.1 手动实现读取数据集

def data_iter(batch_size, features, labels):
    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.2 简洁实现读取数据集

def load_array(data_arrays, batch_size, is_train=True):  #@save
    """构造一个PyTorch数据迭代器"""
    dataset = data.TensorDataset(*data_arrays)  #返回TensorDataset类实例
    return data.DataLoader(dataset, batch_size, shuffle=is_train) #shuffle表明是否乱序

batch_size = 10
data_iter = load_array((features, labels), batch_size)

3. 初始化模型参数

3.1 手动初始化

w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

3.2 简洁实现初始化

net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)

其中net为下面简洁定义的模型。

4. 定义模型

4.1 手动定义

def linreg(X, w, b):  #@save
    """线性回归模型"""
    return torch.matmul(X, w) + b

4.2 简洁定义

# nn是神经网络的缩写
from torch import nn

net = nn.Sequential(nn.Linear(2, 1))

5. 定义损失函数

5.1 手动定义

def squared_loss(y_hat, y):  #@save
    """均方损失"""
    return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2

5.2 简洁定义

loss = nn.MSELoss()   #该loss具有求和功能

6. 定义优化算法

6.1 手动定义

def sgd(params, lr, batch_size):  #@save
    """小批量随机梯度下降"""
    with torch.no_grad():
        for param in params:
            param -= lr * param.grad / batch_size
            param.grad.zero_()

6.2 简洁定义

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

7. 训练

7.1 手动训练

lr = 0.03
num_epochs = 3
net = linreg
loss = squared_loss

for epoch in range(num_epochs):
    for X, y in data_iter(batch_size, features, labels):
        l = loss(net(X, w, b), y)  # X和y的小批量损失
        # 因为l形状是(batch_size,1),而不是一个标量。l中的所有元素被加到一起,
        # 并以此计算关于[w,b]的梯度
        l.sum().backward()
        sgd([w, b], lr, batch_size)  # 使用参数的梯度更新参数
    with torch.no_grad():
        train_l = loss(net(features, w, b), labels)
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')

7.2 简洁训练

num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:
        l = loss(net(X) ,y)
        trainer.zero_grad()
        l.backward()
        trainer.step()
    l = loss(net(features), labels)
    print(f'epoch {epoch + 1}, loss {l:f}')

三、逻辑回归

逻辑回归即类似于分类问题,通常我们有二分类以及多分类问题,二分类我们常选用sigmoid函数,而多分类问题,我们常选用softmax函数,因此也可称为softmax回归。

3.1 二分类回归

3.1.1 二分类回归的大致流程

在上述的单层线性回归中对与每个样本我们会得到一个预测值,我们只需要把这个预测值一分为二,如果预测值在某个区域那么它就属于类别1,否则就属于类别2。 然后根据真实标签值不断的训练权重,从而实现二分类。

3.1.2 sigmoid函数

sigmoid函数的表达式为:
σ ( x ) = 1 1 + e − x \sigma(x)=\frac{1}{1+e^{-x}} σ(x)=1+ex1

它的图像如下:
在这里插入图片描述
它可以把整个实数域的值映射到0到1之间,刚好0-0.5属于一类,0.5-1属于一类。

因此调整之后的公式为:
σ = 1 1 + e − X w \sigma = \frac{1}{1 + e^{-Xw}} σ=1+eXw1

其中 σ \sigma σ可看作属于某一类别的概率。

3.1.3 定义损失函数

设预测类别1的概率为 P 1 = σ P_1 = \sigma P1=σ,预测类别为2的概率为 P 2 = 1 − σ P_2 = 1-\sigma P2=1σ

在某个样本以及权重下,预测值的概率可描述为:
P ( y ^ i ∣ x i , w ) = P 1 y i ∗ P 0 1 − y i P(\hat{y}_i|x_i,w) = P^{y_i}_1 * P^{1-y_i}_0 P(y^ixi,w)=P1yiP01yi
其中 y i y_i yi表示该样本的真实值,当其为1时, P ( y ^ i ∣ x i , w ) = P 1 P(\hat{y}_i|x_i,w) =P_1 P(y^ixi,w)=P1 此时若 P 1 P_1 P1越接近1越损失越小;当其为0时, P ( y ^ i ∣ x i , w ) = P 0 P(\hat{y}_i|x_i,w) =P_0 P(y^ixi,w)=P0 此时若 P 0 P_0 P0越接近1越损失越小。

因此总的样本概率为:
P = ∏ i = 1 m P ( y ^ i ∣ x i , w ) = ∏ i = 1 m ( P 1 y i ∗ P 0 1 − y i ) = ∏ i = 1 m ( σ i y i ∗ ( 1 − σ i ) 1 − y i ) \begin{aligned} P& =\prod\limits_{i=1}^{m}P(\hat{y}_i|x_i,w) \\ &=\prod\limits_{i=1}^m(P_1^{y_i}*P_0^{1-y_i}) \\ &=\prod\limits_{i=1}^m(\sigma_i^{y_i}*(1-\sigma_i)^{1-y_i}) \end{aligned} P=i=1mP(y^ixi,w)=i=1m(P1yiP01yi)=i=1m(σiyi(1σi)1yi)

我们通常去负对数来获得损失函数:
l o s s = − ∑ i = 1 m ( y i ∗ l n ( σ i ) + ( 1 − y i ) ∗ l n ( 1 − σ i ) ) loss = -\sum\limits_{i=1}^m(y_i*ln(\sigma_i)+(1-y_i)*ln(1-\sigma_i)) loss=i=1m(yiln(σi)+(1yi)ln(1σi))

3.1.4 手动代码实现

import torch
from torch import nn
from torch.utils import data

num_samples = 500
num_inputs = 200
num_outputs = 1
batch_size = 20
num_epochs = 30

# 生成数据
features = torch.rand((num_samples, num_inputs), dtype=torch.float32)
labels = torch.randint(low=0, high=2, size=(num_samples, 1))
dataset = data.TensorDataset(features, labels)
train_loader = data.DataLoader(dataset, batch_size=20, shuffle=True)

# 初始化模型参数
W = torch.normal(0, 0.01, size=(num_inputs, 1), requires_grad=True)
b = torch.zeros(num_outputs, requires_grad=True)


# 模型
def net(X, W, b):
    z = torch.mm(X, W) + b
    sigma = torch.sigmoid(z)
    return sigma


# 损失函数
def myBCEWithLogitsLoss(outputs, labels):
    loss = -(labels * torch.log(outputs) + (1 - labels) * torch.log(1 - outputs))
    loss = torch.mean(loss)
    return loss


# 优化算法
def sgd(W, b, lr, batch_size):  # @save
    """小批量随机梯度下降"""
    with torch.no_grad():
        W -= lr * W.grad / batch_size
        b -= lr * b.grad / batch_size


# 训练
for epoch in range(num_epochs):
    for X, y in train_loader:
        loss = myBCEWithLogitsLoss(net(X, W, b), y)
        loss.backward()
        sgd(W, b, 0.03, batch_size)
    l_hat = net(features, W, b)
    loss = myBCEWithLogitsLoss(l_hat, labels)
    l_hat_int = torch.tensor(
        [1 if l_hat[i] > 0.5 else 0 for i in range(l_hat.shape[0])]
    )
    accuracy = torch.mean((l_hat_int.flatten() == labels.flatten()).float())
    print(f"epoch {epoch + 1}, loss {loss:f}, acc {accuracy}")

3.2 多分类回归

3.2.1 网络架构

在这里插入图片描述
其中, o 1 = x 1 w 11 + x 2 w 12 + x 3 w 13 + x 4 w 14 + b 1 , o 2 = x 1 w 21 + x 2 w 22 + x 3 w 23 + x 4 w 24 + b 2 , o 3 = x 1 w 31 + x 2 w 32 + x 3 w 33 + x 4 w 34 + b 3 . \begin{split}\begin{aligned} o_1 &= x_1 w_{11} + x_2 w_{12} + x_3 w_{13} + x_4 w_{14} + b_1,\\ o_2 &= x_1 w_{21} + x_2 w_{22} + x_3 w_{23} + x_4 w_{24} + b_2,\\ o_3 &= x_1 w_{31} + x_2 w_{32} + x_3 w_{33} + x_4 w_{34} + b_3. \end{aligned}\end{split} o1o2o3=x1w11+x2w12+x3w13+x4w14+b1,=x1w21+x2w22+x3w23+x4w24+b2,=x1w31+x2w32+x3w33+x4w34+b3.

3.2.2 大致流程

O = X W + b , Y ^ = s o f t m a x ( O ) . \begin{split}\begin{aligned} \mathbf{O} &= \mathbf{X} \mathbf{W} + \mathbf{b}, \\ \hat{\mathbf{Y}} & = \mathrm{softmax}(\mathbf{O}). \end{aligned}\end{split} OY^=XW+b,=softmax(O).
先线性变换 再用softmax函数进行非线性变换。

3.2.3 softmax函数

y ^ = s o f t m a x ( o ) 其中 y ^ j = exp ⁡ ( o j ) ∑ k exp ⁡ ( o k ) \hat{\mathbf{y}} = \mathrm{softmax}(\mathbf{o})\quad \text{其中}\quad \hat{y}_j = \frac{\exp(o_j)}{\sum_k \exp(o_k)} y^=softmax(o)其中y^j=kexp(ok)exp(oj)

3.2.4 损失函数

每个样本的输出值都可以采用独热编码的方式进行表达,如进行3分类回归,若一样本对应的标签是第0分类,则其独热编码为1,0,0。

k分类损失函数推导:
P ( y ^ i ∣ x i , w ) = P 1 y i ( k − 1 ) ∗ P 2 y i ( n − 2 ) ∗ P 3 y i ( k − 3 ) ∗ … ∗ P K y i ( k − K ) P(\hat{y}_{i}|x_{i},w)=P_{1}^{y_i(k-1)}*P_{2}^{y_i(n-2)}*P_{3}^{y_i(k-3)}*\ldots*P_{K}^{y_i(k-K)} P(y^ixi,w)=P1yi(k1)P2yi(n2)P3yi(k3)PKyi(kK)

取负对数可得损失函数为:
l ( y , y ^ ) = − ∑ j = 1 q y j log ⁡ y ^ j . l(\mathbf{y}, \hat{\mathbf{y}}) = - \sum_{j=1}^q y_j \log \hat{y}_j. l(y,y^)=j=1qyjlogy^j.

其中,q表示样本数 y j y_j yj是一个长度为k独热编码, y ^ j \hat{y}_j y^j也是一个长度为k的向量,每一个值为该类别的概率。

此损失函数称为交叉熵损失函数

3.2.5 避免softmax函数上溢以及对数下溢

由于softmax中有指数函数,容易造成数值上溢,解决办法:
y ^ j = exp ⁡ ( o j − max ⁡ ( o k ) ) exp ⁡ ( max ⁡ ( o k ) ) ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) exp ⁡ ( max ⁡ ( o k ) ) = exp ⁡ ( o j − max ⁡ ( o k ) ) ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) . \begin{split}\begin{aligned} \hat y_j & = \frac{\exp(o_j - \max(o_k))\exp(\max(o_k))}{\sum_k \exp(o_k - \max(o_k))\exp(\max(o_k))} \\ & = \frac{\exp(o_j - \max(o_k))}{\sum_k \exp(o_k - \max(o_k))}. \end{aligned}\end{split} y^j=kexp(okmax(ok))exp(max(ok))exp(ojmax(ok))exp(max(ok))=kexp(okmax(ok))exp(ojmax(ok)).

但此做法,可能会导致其值接近0,从而导致下溢,并且导致交叉熵损失函数中的取对数导致负无穷从而又上溢,解决办法:把两者结合
log ⁡ ( y ^ j ) = log ⁡ ( exp ⁡ ( o j − max ⁡ ( o k ) ) ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) ) = log ⁡ ( exp ⁡ ( o j − max ⁡ ( o k ) ) ) − log ⁡ ( ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) ) = o j − max ⁡ ( o k ) − log ⁡ ( ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) ) . \begin{split}\begin{aligned} \log{(\hat y_j)} & = \log\left( \frac{\exp(o_j - \max(o_k))}{\sum_k \exp(o_k - \max(o_k))}\right) \\ & = \log{(\exp(o_j - \max(o_k)))}-\log{\left( \sum_k \exp(o_k - \max(o_k)) \right)} \\ & = o_j - \max(o_k) -\log{\left( \sum_k \exp(o_k - \max(o_k)) \right)}. \end{aligned}\end{split} log(y^j)=log(kexp(okmax(ok))exp(ojmax(ok)))=log(exp(ojmax(ok)))log(kexp(okmax(ok)))=ojmax(ok)log(kexp(okmax(ok))).

3.2.6 softmax回归代码实现

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)

##定义模型
# PyTorch不会隐式地调整输入的形状。因此,
# 我们在线性层前定义了展平层(flatten),来调整网络输入的形状,softmax无需加
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)

# 定义损失函数 已经融入softmax
loss = nn.CrossEntropyLoss(reduction="none")

# 定义优化算法
trainer = torch.optim.SGD(net.parameters(), lr=0.1)

# 训练
num_epochs = 10


if __name__ == "__main__":
    for epoch in range(num_epochs):
        acc = 0
        for X, y in train_iter:
            y_hat = net(X)
            l = loss(y_hat, y)
            trainer.zero_grad()
            l.mean().backward()
            trainer.step()
        print(l.mean())

总结

本节主要讲解了线性回归以及逻辑回归及其代码实现,两者都是单层神经网络,下章将讲解多层感知机。

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

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

相关文章

基于SpringBoot+Vue的自习室预订系统设计与实现

博主介绍: 大家好,我是一名在Java圈混迹十余年的程序员,精通Java编程语言,同时也熟练掌握微信小程序、Python和Android等技术,能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

深度学习卷积神经网络CNN之ResNet模型网络详解说明(超详细理论篇)

1.ResNet背景 2. ResNet论文 3. ResNet模型结构 4. ResNet优缺点 一、ResNet背景 ResNet 在2015 年由微软研究院提出的一种深度卷积神经网络结构,在ILSVRC(ImageNet Large Scale Visual Recognition Challenge)中取得了冠军(分类…

OpenCV(图像处理)-基于Python-形态学处理-开运算、闭运算、顶帽、黑帽运算

1. 形态学2. 常用接口2.1 cvtColor()2.2 图像二值化threshod()自适应阈值二值化adaptiveThreshod() 2.3 腐蚀与膨胀erode()getStructuringElement()dilate() 2.4开、闭、梯度、顶帽、黑帽运算morphologyEx() 1. 形态学 OpenCV形态学是一种基于OpenCV库的数字图像处理技术&…

如何安装MySQL数据库

目录 什么是MySQL数据库 第一步 安装依赖环境 第二步 创建MySQL相关进程用户 第三步 导入MySQL相关包 第四步 解包到指定目录下 第五步 切换到MySQL目录下编译安装 第六步 编译 第七步 更改指定文件的所有者和所属组 第八步 进入指定配置文件清空内容 第九步 配置指定…

IDEA Build Artifacts 功能使用总结

文章目录 创建Artifact步骤Build Artifact步骤 打开IDEA,在没有创建Artifact时,菜单"Build -> Build Artifacts…“是灰色的,不可用状态。 所以,第一步是进入"File -> Project Structure…”,创建Arti…

12-代码实战——服务器版表白墙

目录 1.版本一:将数据存到内存中 ①约定前后端交互接口 a.添加表白信息: b.查询表白列表: ②在webapp包下创建message-wall.html前端文件 ③在java包下创建AddMessageServlet后端类 ④在java包下创建MessageListServlet后端类 2.版本…

【Azure】微软 Azure 基础解析(七)Azure 网络服务中的虚拟网络 VNet、网关、负载均衡器 Load Balancer

本系列博文还在更新中,收录在专栏:「Azure探秘:构建云计算世界」 专栏中。 本系列文章列表如下: 【Azure】微软 Azure 基础解析(三)描述云计算运营中的 CapEx 与 OpEx,如何区分 CapEx 与 OpEx…

通过 Python 封装关键词搜索阿里巴巴商品api接口

以下是使用 Python 封装关键词搜索阿里巴巴商品列表数据的步骤: 使用 requests 库向阿里巴巴搜索接口发送 HTTP 请求,可以使用 GET 或 POST 方法,请求参数中应包含搜索关键词、每页展示数量、当前页码等信息。 解析返回的 response 中的 HTM…

【Java高级语法】(六)内部类Inner Class:这可能是史上最全的关于内部类的学习资料~

Java高级语法详解之包装类 :one: 概念:two: 优缺点:three: 使用2.1 成员内部类2.2 局部内部类2.3 匿名内部类2.4 静态内部类2.5 小结:外部类访问四种内部类的特点2.6 小结:其他类访问四种内部类的特点 :four: 内部类与外部类的关系:five: 应用场景:six: …

01-抒写代码之诗:Golang 关键字的文学探索

📃个人主页:个人主页 🔥系列专栏:Golang基础 💬Go(又称Golang)是由Google开发的开源编程语言。它结合了静态类型的安全性和动态语言的灵活性,拥有高效的并发编程能力和简洁的语法。G…

Jenkins结合gitee自动化部署SpringBoot项目

安装 安装教程 插件选择 Gitee Plugin 配置 源码管理 填写源码地址 注意:请确保genkins所在的服务器有权限git拉取远程仓库代码,如果不可以请参考ssh配置centos 配置ssh拉取远程git代码 源码管理 构建触发器 1.勾选Gitee webhook 触发构建 2.生成we…

论文笔记:MEASURING DISENTANGLEMENT: A REVIEW OF METRICS

0 摘要 学习解缠和表示数据中的变化因素是人工智能中的一个重要问题。虽然已经取得了许多关于学习这些表示的进展,但如何量化解缠仍然不清楚。 虽然存在一些度量标准,但对它们的隐含假设、真正衡量的内容以及限制了解甚少。因此,当比较不同的…

一键开启GPT 平行时空模式

不知道大家日常使用GPT的时候,在一次会话中是如何完成同类任务的对话的? 简单点来说,假设你已经完成了角色设定,比如你设定GPT是一名文案编辑,那么接下来你会多次给它提交稿件让它进行编辑,那么在多次提交的时候&…

抽象工厂模式

一.定义 抽象工厂模式(Abstract Factory Pattern)是一种比较常用的模式,其定义如下: Provide an interface for creating families of related or dependent objects without specifyingtheir concrete classes.(为创建一组相关或相互依赖的对象提供一个接口&#…

算法刷题-双指针-二分法

27. 移除元素 力扣题目链接 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。 元素的顺序可以改变。你不需…

Web前端开发技术储久良第三版课后答案

P16-第1章 练习与实验答案 练习1 1.选择题 (1)B (2)B (3)B (4)D (5)A 2.填空题 (1)标记、文本 (2)Tim Berners-Lee(蒂姆伯纳斯李) (3)查看 (4)NotePad、EditPlus、TextPad、TopStyle、UltraEdit等 (5)超文本标记语言、统一资源定位符(器&am…

Axios和Spring MVC[前端和后端的请求和响应处理]

在前后端交互中,Axios和Spring MVC扮演着不同的角色,分别负责前端和后端的请求和响应处理。它们之间的作用如下: Axios(前端): 发送HTTP请求:前端使用Axios库发送HTTP请求到后端。可以使用Axi…

webpack生产模式配置

一、生产模式和开发模式介绍 生成模式(production mode)是指在开发完成后将代码部署到生产环境中运行的模式,通常需要进行代码压缩、优化、合并,以减少文件大小和请求次数,提高页面加载速度和运行效率。 开发模式&am…

02_LinuxLED驱动开发

目录 Linux下LED灯驱动原理 地址映射 ioremap函数 iounmap函数 I/O内存访问函数 LED灯驱动程序编写 编写测试APP 编译驱动程序 编译测试APP 运行测试 Linux下LED灯驱动原理 Linux下的任何外设驱动,最终都是要配置相应的硬件寄存器。所以LED灯驱动最终也是对I.MX6ULL…

LVS-DR群集部署

目录 一、LVS-DR数据包流向分析 二、 DR 模式的特点 总结 三、LVS-DR中的ARP问题 1.在局域网中具有相同的IP地址,势必会造成各服务器ARP通信的紊乱 2.路由器根据ARP表项,会将新来的请求报文转发给RealServer,导致Director的VIP失效 3.解…