吴恩达《机器学习》——Logistics回归代码实现

news2024/11/15 11:49:06

Logisitc回归

  • 1. Sigmoid与二分类
    • Sigmoid函数
    • 为什么Sigmoid函数可以表示二分类概率?
  • 2. Logistics回归
    • 交叉熵损失函数
    • 梯度
    • 过拟合与欠拟合
    • 正则化
  • 3. Python代码实现
  • 4. 单维与多维Logistic分类
    • 单维数据分类
    • 多维数据分类

数据集、源文件可以在Github项目中获得
链接: https://github.com/Raymond-Yang-2001/AndrewNg-Machine-Learing-Homework

1. Sigmoid与二分类

与线性回归不同,Logistic回归虽然名为回归,却常常被用来实现分类的功能。其与线性回归的不同之处仅仅在于在线性回归的输出后添加了一个Sigmoid函数,使其输出能表示分类的概率,而不会预测值。至于为什么Sigmoid函数会有这样的功能,我们在接下来会说明。

Sigmoid函数

Sigmoid函数的数学表达式如下所示:
σ ( x ) = 1 1 + e − x \sigma(x)=\frac{1}{1+e^{-x}} σ(x)=1+ex1
分析可得,Sigmoid函数是一个递增函数,x值越大, σ ( x ) \sigma(x) σ(x)越接近1,x值越小, σ ( x ) \sigma(x) σ(x)越接近0。当x=0的时候, σ ( x ) = 0.5 \sigma(x)=0.5 σ(x)=0.5。其函数曲线图如下所示:
在这里插入图片描述

为什么Sigmoid函数可以表示二分类概率?

这里我们先来回顾一下伯努利分布的知识。

伯努利分布指的是对于随机变量 X X X有, 参数为 p ( 0 < p < 1 ) p(0<p<1) p(0<p<1),如果它分别以概率 p p p 1 − p 1-p 1p取1和0为值。 E ( X ) = p E(X)= p E(X)=p, D ( X ) = p ( 1 − p ) D(X)=p(1-p) D(X)=p(1p)。伯努利试验成功的次数服从伯努利分布,参数 p p p是试验成功的概率。伯努利分布是一个离散型机率分布,是 N = 1 N=1 N=1时二项分布的特殊情况

对于伯努利分布,我们有 p = μ x ( 1 − μ ) ( 1 − x ) p=\mu^{x}(1-\mu)^{(1-x)} p=μx(1μ)(1x),对等式做变换,有
p = e x ln ⁡ μ + ( 1 − x ) ln ⁡ ( 1 − μ ) = e x ln ⁡ μ 1 − μ + ln ⁡ ( 1 − μ ) p=e^{x\ln{\mu}+(1-x)\ln{(1-\mu)}}=e^{x\ln{\frac{\mu}{1-\mu}}+\ln{(1-\mu)}} p=exlnμ+(1x)ln(1μ)=exln1μμ+ln(1μ)
接下来,我们使用指数族分布来表示伯努利分布。

指数族分布(exponential family of distributions)亦称指数型分布族,是统计中最重要的参数分布族

指数族分布的一般参数化表示为:
p ( y ; η ) = b ( y ) e η ⊤ T ( y ) − α ( η ) p(y;\eta)=b(y)e^{\eta^{\top}T(y)-\alpha(\eta)} p(y;η)=b(y)eηT(y)α(η)
其中,

  • y y y是自然参数
  • T ( y ) T(y) T(y) y y y的充分统计量
  • α ( η ) \alpha(\eta) α(η)是对数部分函数,用来确保 ∑ p ( y ; η ) = 1 \sum{p(y;\eta)}=1 p(y;η)=1

由此式可以得到, η = ln ⁡ μ 1 − μ \eta=\ln{\frac{\mu}{1-\mu}} η=ln1μμ,即
μ = 1 1 + e − η \mu=\frac{1}{1+e^{-\eta}} μ=1+eη1

由此可得,Sigmoid函数是可以表示伯努利分布的概率的。

2. Logistics回归

与线性回归一样,Logistic回归同样可以采用基于梯度的优化方法来求解。Logistic回归的模型公式如下所示:
h ( x ; θ ) = σ ( θ x ⊤ ) h(\boldsymbol{x};\boldsymbol{\theta})=\sigma{(\boldsymbol{\theta x^{\top}})} h(x;θ)=σ(θx)
其中, x \boldsymbol{x} x是维度为 ( n , d + 1 ) (n,d+1) (n,d+1)的样本(补充添加第一维度全为1,便于偏置项的运算), θ \boldsymbol{\theta} θ ( 1 , d + 1 ) (1,d+1) (1,d+1)的参数。得到 ( 1 , n ) (1,n) (1,n)的输出。

交叉熵损失函数

在线性回归中,我们可以使用均方误差MSE来衡量预测值和真实值之间的差异,这种基于数值差异的损失函数很容易被理解。但是在分类任务当中,MSE显然已经不适合衡量分类的差异了,为此我们引入了一个全新的损失函数——交叉熵损失。

为了理解交叉熵损失,我们先从信息论的一个重要概念——KL散度入手。

在分类任务当中,无论是多分类还是二分类,我们的任务可以看做要输出一个预测的分布。对于二分类,这是一个伯努利分布,对于多分类,这是一个多项式分布。分类的效果越好,这个输出的分布和目标分布应当越接近。那么如何衡量两个分布的相似度?这就是KL散度的作用。

考虑一个 K K K类的分类问题,设我们的目标分布为 q ( k ∣ x ) q(k|x) q(kx),输出的分布为 p ( k ∣ x ) p(k|x) p(kx)。这两个分布分别指明了样本为第 k k k类的概率。对于目标分布,显而易见这是一个one-hot样式的分布,即在真是类别的概率为1,其余概率均为0。两个分布的KL散度写作:
K L ( q ∣ ∣ p ) = ∑ k = 1 K q ( k ∣ x ) log ⁡ q ( k ∣ x ) p ( k ∣ x ) KL(q||p)=\sum_{k=1}^{K}{q(k|x)\log{\frac{q(k|x)}{p(k|x)}}} KL(q∣∣p)=k=1Kq(kx)logp(kx)q(kx)
两个分布越接近,KL散度越小。可以观察到,当 p = q p=q p=q的时候,KL散度为0。

如果我们将KL散度进一步展开,可以得到:
K L ( q ∣ ∣ p ) = ∑ k = 1 K q ( k ∣ x ) log ⁡ q ( k ∣ x ) − q ( k ∣ x ) log ⁡ p ( k ∣ x ) KL(q||p)=\sum_{k=1}^{K}{q(k|x)\log{q(k|x)}-q(k|x)\log{p(k|x)}} KL(q∣∣p)=k=1Kq(kx)logq(kx)q(kx)logp(kx)
前半部分是关于分布 q q q的常数,考虑到分布 q q q是固定的目标分布,KL散度只与后半部分有关,也被叫做交叉熵。
C r o s s E n t r o p y = − ∑ k = 1 K q ( k ∣ x ) log ⁡ p ( k ∣ x ) CrossEntropy=-\sum_{k=1}^{K}q(k|x)\log{p(k|x)} CrossEntropy=k=1Kq(kx)logp(kx)
两个分布越接近,交叉熵越小,反之,交叉熵越大。

特别地,对于二分类任务,存在二分类交叉熵BCE(Binary Cross Entropy):
B C E = − ( y log ⁡ y ^ + ( 1 − y ) log ⁡ ( 1 − y ^ ) ) BCE=-(y\log{\hat{y}}+(1-y)\log{(1-\hat{y})}) BCE=(ylogy^+(1y)log(1y^))
这其实是 K = 2 K=2 K=2的特殊情况。

梯度

Logistic回归的梯度表示与线性回归一样,都为
θ j = θ j − α 1 m ∑ i = 1 m ( h ( x ( i ) ; θ ) − y ( i ) ) x j ( i ) \theta_{j}=\theta_{j}-\alpha\frac{1}{m}\sum_{i=1}^{m}{(h(x^{(i)};\theta)-y^{(i)})x_{j}^{(i)}} θj=θjαm1i=1m(h(x(i);θ)y(i))xj(i)
注意,在Logistic回归中, h ( x ; θ ) = σ ( θ x ⊤ ) h(\boldsymbol{x};\boldsymbol{\theta})=\sigma{(\boldsymbol{\theta x^{\top}})} h(x;θ)=σ(θx),在线性回归中,则没有Sigmoid的运算。

过拟合与欠拟合

在机器学习领域,过拟合始终是一个重要的问题。过拟合指的是学习到的模型偏差小,方差过大的情况。

举例来说,存在一个较大的分类用数据集,这个数据集的标签符合一定的分布,模型的目标是学习从样本到这个分布的映射。假设我们将这个数据集随机分成10个子集,分别训练出对应的十个模型,这十个模型应当都能在自己的数据集上进行较好地分类,同时模型的之间的差距应该不会很大——因为所有的数据都来自一个数据集。这就意味着模型的偏差和方差都比较小

考虑一种情况,假设其中一个数据集中包括的“狗”的样本都是白色的狗,这个模型认为所有白色的动物就都是狗。这虽然能在“白狗”的数据集上进行很好地分类,但是相较于其他模型,这个模型的“差异”显得过大。这就是偏差小的情况下,方差变大。也叫做过拟合。

反之,如果偏差很大,方差很小,即模型之间的差异都很小,但都不能准确分类,这种情况叫做欠拟合

对于欠拟合,我们可以通过数据增强,或者暴力提高迭代次数来解决。对于过拟合,我们将介绍一种叫做正则化的方法。

正则化

最常用的正则化方式,是在损失函数后面附加一个参数的惩罚项,以控制参数不要向过拟合的方向发展。通用的表达形式为:
R e g u l a r i z e d   l o s s = L o s s + λ ( θ ) Regularized\ loss = Loss + \lambda(\theta) Regularized loss=Loss+λ(θ)
在本代码中,我们实现 L 2 L^{2} L2正则化。
正则化损失函数如下所示:
J ( θ ) = 1 m ∑ i = 1 m [ − y ( i ) log ⁡ ( h θ ( x ( i ) ) ) − ( 1 − y ( i ) ) log ⁡ ( 1 − h θ ( x ( i ) ) ) ] + λ 2 m ∑ j = 1 n θ j 2 J\left( \theta \right)=\frac{1}{m}\sum\limits_{i=1}^{m}{[-{{y}^{(i)}}\log \left( {{h}_{\theta }}\left( {{x}^{(i)}} \right) \right)-\left( 1-{{y}^{(i)}} \right)\log \left( 1-{{h}_{\theta }}\left( {{x}^{(i)}} \right) \right)]}+\frac{\lambda }{2m}\sum\limits_{j=1}^{n}{\theta _{j}^{2}} J(θ)=m1i=1m[y(i)log(hθ(x(i)))(1y(i))log(1hθ(x(i)))]+2mλj=1nθj2
我们对其求梯度,可以得到正则化后的梯度:
g ( θ ) = 1 m ∑ i = 1 m ( h ( x ( i ) ; θ ) − y ( i ) ) x j ( i ) + λ m θ j g(\theta)=\frac{1}{m}\sum_{i=1}^{m}{(h(x^{(i)};\theta)-y^{(i)})x_{j}^{(i)}}+\frac{\lambda }{m}\theta _{j} g(θ)=m1i=1m(h(x(i);θ)y(i))xj(i)+mλθj
利用正则化的梯度更新参数,可以得到:
θ j = θ j − α 1 m ∑ i = 1 m ( h ( x ( i ) ; θ ) − y ( i ) ) x j ( i ) − λ m ∑ j = 1 n θ j = ( 1 − λ m ) θ j − α 1 m ∑ i = 1 m ( h ( x ( i ) ; θ ) − y ( i ) ) x j ( i ) \theta_{j}=\theta_{j}-\alpha\frac{1}{m}\sum_{i=1}^{m}{(h(x^{(i)};\theta)-y^{(i)})x_{j}^{(i)}}-\frac{\lambda }{m}\sum\limits_{j=1}^{n}{\theta _{j}}=\left(1-\frac{\lambda }{m}\right)\theta_{j}-\alpha\frac{1}{m}\sum_{i=1}^{m}{(h(x^{(i)};\theta)-y^{(i)})x_{j}^{(i)}} θj=θjαm1i=1m(h(x(i);θ)y(i))xj(i)mλj=1nθj=(1mλ)θjαm1i=1m(h(x(i);θ)y(i))xj(i)
可以看出,正则化实际上是对参数进行了一定程度的缩小。缩小的程度与 λ / m \lambda / m λ/m 有关。
在这里插入图片描述
此图说明了 L 2 L^{2} L2正则化的参数的影响。虚线表示正则化项的损失等值线,实线表示未正则化损失函数的损失等值线。两者在 w ~ \tilde{w} w~达到平衡。在 w 1 w_{1} w1方向,参数变化的时候,损失函数并不会变化太多,但在 w 2 w_{2} w2这种变化显得更为剧烈。也就是说 w 2 w_{2} w2相比 w 1 w_{1} w1更能显著地减小损失函数值。

L 2 L^{2} L2正则化使得显著减小损失函数值方向上的参数保存更完好,无助于损失函数减小的方向改变较大,因为这不会显著的影响梯度。

3. Python代码实现

这里给出Logistic回归类的代码 ,同时也实现了数据的归一化和正则化:

import numpy as np


def sigmoid(x):
    return 1 / (1 + np.exp(-x))


def bce_loss(pred, target):
    """
    计算误差
    :param pred: 预测
    :param target: ground truth
    :return: 损失序列
    """
    return np.mean(-target * np.log(pred))


class LogisticRegression:
    """
    Logistic回归类
    """

    def __init__(self, x, y, val_x, val_y, epoch=100, lr=0.1, normalize=True, regularize=None, scale=0, show=True):
        """
        初始化
        :param x: 样本, (sample_number, dimension)
        :param y: 标签, (sample_numer, 1)
        :param epoch: 训练迭代次数
        :param lr: 学习率
        """
        self.theta = None
        self.loss = []
        self.val_loss = []
        self.n = x.shape[0]
        self.d = x.shape[1]

        self.epoch = epoch
        self.lr = lr

        t = np.ones(shape=(self.n, 1))

        self.normalize = normalize

        if self.normalize:
            self.x_std = x.std(axis=0)
            self.x_mean = x.mean(axis=0)
            self.y_mean = y.mean(axis=0)
            self.y_std = y.std(axis=0)
            x = (x - self.x_mean) / self.x_std

        self.y = y
        self.x = np.concatenate((t, x), axis=1)

        # self.val_x = (val_x - val_x.mean(axis=0)) / val_x.std(axis=0)
        self.val_x = val_x
        self.val_y = val_y

        self.regularize = regularize
        self.scale = scale

        self.show = show

    def init_theta(self):
        """
        初始化参数
        :return: theta (1, d+1)
        """
        self.theta = np.zeros(shape=(1, self.d + 1))

    def gradient_decent(self, pred):
        """
        实现梯度下降求解
        """
        # error (n,1)
        error = pred - self.y
        # term (d+1, 1)
        term = np.matmul(self.x.T, error)
        # term (1,d+1)
        term = term.T

        if self.regularize == "L2":
            re = self.scale / self.n * self.theta[0, 1:]
            re = np.expand_dims(np.array(re), axis=0)
            re = np.concatenate((np.array([[0]]), re), axis=1)
            # re [0,...] (1,d+1)
            self.theta = self.theta - self.lr * (term / self.n + re)
        # update parameters
        else:
            self.theta = self.theta - self.lr * (term / self.n)

    def validation(self, x, y):
        if self.normalize:
            x = (x - x.mean(axis=0)) / x.std(axis=0)
        outputs = self.get_prob(x)
        curr_loss = bce_loss(outputs, y)
        if self.regularize == "L2":
            curr_loss += self.scale / self.n * np.sum(self.theta[0, 1:] ** 2)
        self.val_loss.append(curr_loss)
        predicted = np.expand_dims(np.where(outputs[:, 0] > 0.5, 1, 0), axis=1)
        count = np.sum(predicted == y)
        if self.show:
            print("Accuracy on Val set: {:.2f}%\tLoss on Val set: {:.4f}".format(count / y.shape[0] * 100, curr_loss))

    def test(self, x, y):
        outputs = self.get_prob(x)
        predicted = np.expand_dims(np.where(outputs[:, 0] > 0.5, 1, 0), axis=1)
        count = np.sum(predicted == y)
        # print("Accuracy on Test set: {:.2f}%".format(count / y.shape[0] * 100))
        # curr_loss = bce_loss(outputs, y)
        # if self.regularize == "L2":
        # curr_loss += self.scale / self.n * np.sum(self.theta[0, 1:] ** 2)
        return count / y.shape[0]  # , curr_loss

    def train(self):
        """
        训练Logistic回归
        :return: 参数矩阵theta (1,d+1); 损失序列 loss
        """
        self.init_theta()

        for i in range(self.epoch):
            # pred (1,n); theta (1,d+1); self.x.T (d+1, n)
            z = np.matmul(self.theta, self.x.T).T
            # pred (n,1)
            pred = sigmoid(z)
            curr_loss = bce_loss(pred, self.y)
            if self.regularize == "L2":
                curr_loss += self.scale / self.n * np.sum(self.theta[0, 1:] ** 2)
            self.loss.append(curr_loss)
            self.gradient_decent(pred)
            if self.show:
                print("Epoch: {}/{}, Train Loss: {:.4f}".format(i + 1, self.epoch, curr_loss))
            self.validation(self.val_x, self.val_y)

        if self.normalize:
            y_mean = np.mean(z, axis=0)
            self.theta[0, 1:] = self.theta[0, 1:] / self.x_std.T
            self.theta[0, 0] = y_mean - np.dot(self.theta[0, 1:], self.x_mean.T)
        return self.theta, self.loss, self.val_loss

    def get_prob(self, x):
        """
        回归预测
        :param x: 输入样本 (n,d)
        :return: 预测结果 (n,1)
        """
        t = np.ones(shape=(x.shape[0], 1))
        x = np.concatenate((t, x), axis=1)
        pred = sigmoid(np.matmul(self.theta, x.T))
        return pred.T

    def get_inner_product(self, x):
        t = np.ones(shape=(x.shape[0], 1))
        x = np.concatenate((t, x), axis=1)
        return np.matmul(self.theta, x.T)

    def predict(self, x):
        prob = self.get_prob(x)
        return np.expand_dims(np.where(prob[:, 0] > 0.5, 1, 0), axis=1)

4. 单维与多维Logistic分类

单维数据分类

数据集可视化
在这里插入图片描述
划分训练集和验证集
训练集可视化:
在这里插入图片描述
验证集可视化:
在这里插入图片描述
调用算法进行分类

from LogisticRegression import LogisticRegression

epochs = 5000
alpha = 0.01
logistic_reg = LogisticRegression(x=train_x,y=train_y_ex,val_x=val_x,val_y=val_y_ex,epoch=epochs,lr=alpha)
theta,train_loss,val_loss = logistic_reg.train()

分类性能

Accuracy on Test Set: 80.00%
My F1 Score: 0.8571

sklearn库函数验证

Sklearn Accuracy: 80.00%
Sklearn F1 Score: 0.8571

决策边界可视化
在这里插入图片描述

训练过程可视化
可以看到有明显的过拟合出现,这可以通过调整学习率和迭代次数等来抑制过拟合,当然也可以进行正则化。
在这里插入图片描述

多维数据分类

数据集可视化
在这里插入图片描述
划分训练集和验证集
训练集:
在这里插入图片描述
验证集:
在这里插入图片描述

做数据增强(拓展数据维度)
X = [ x 1 , x 2 , x 1 2 , x 1 x 2 , x 2 2 , x 1 3 , x 1 2 x 2 , ⋯   ] \mathbf{X}=[x_{1}, x_{2}, x_{1}^{2}, x_{1}x_{2}, x_{2}^{2}, x_{1}^{3}, x_{1}^{2}x_{2},\cdots] X=[x1,x2,x12,x1x2,x22,x13,x12x2,]
这里扩展到六次方

def feature_mapping(x, degree):
    feature = np.zeros([x.shape[0],1])
    for i in range(0, 1 + degree):
        for j in range(0, 1 + degree - i):
            if i==0 and j==0: continue
            feature=np.concatenate((feature, np.expand_dims(np.multiply(np.power(x[:, 0], i) , np.power(x[:, 1], j)), axis=1)),axis=1)
    return feature[:,1:]

train_x_map = feature_mapping(train_x,degree=6)
val_x_map = feature_mapping(val_x,degree=6)

正则化参数为2

Accuracy on Test Set: 66.67%
My F1 Score: 0.5556
Sklearn Accuracy: 70.83%
Sklearn Val Loss: 0.3076
Sklearn F1 Score: 0.6667

决策边界可视化
在这里插入图片描述
正则化参数为0,决策边界可视化
可以看出决策边界显得过于“畸形”,这是过拟合的突出表现。
在这里插入图片描述

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

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

相关文章

04 kafka 中一些常用的配置的使用

前言 呵呵 也是最近有一些 搭建 kafka 的环境的需求 然后 从新看了一下 一部分的配置情况, 这里 大致理一下 一些我这里比较关心的配置 那些配置关联了 kafka 服务器绑定服务 绑定 tcp 服务的配置来自于这里, 读取的是 config.dataPlaneListeners config.dataPlaneListen…

Java母婴商城母婴店孕妇商城婴幼儿商城网站系统源码

简介 java使用ssm开发的母婴商城系统&#xff0c;用户可以注册浏览商品&#xff0c;加入购物车或者直接下单购买&#xff0c;在个人中心管理收货地址和订单&#xff0c;管理员也就是商家登录后台可以发布商品&#xff0c;上下架商品&#xff0c;处理待发货订单等。 演示视频&…

Allegro如何在PCB上查看pin number的三种方法操作指导

Allegro如何在PCB上查看pin number的三种方法操作指导 Allegro支持快捷的在PCB上查看pin number,如下图 具体操作如下 方法一:show element 选择Show Element命令Find选择Pins

2022年学习机器人和人工智能的一些期待

2022年学习机器人和人工智能的一些体会 2023年即将到来&#xff0c;满满的期待。 做好规划是非常非常重要的&#xff0c;有时候甚至比认真做事本身更为重要。 《礼记中庸》&#xff1a;“凡事豫则立&#xff0c;不豫则废。言前定则不跲&#xff0c;事前定则不困&#xff0c;行…

视频解码学习备忘

媒体文件知识 日常都是播放器直接播&#xff0c;其实这里面还有不少内容的。 首先是视频容器&#xff0c;就是所谓的.mp4 .mkv 这类文件,其目的主要就是用来存放音频视频字幕等内容&#xff0c;所以叫做容器。这些都有一定规范&#xff0c;比如mp4&#xff0c;叫ISO 14496-12…

流程图+BPMN+脑图 JointJS++ 3.6.3 Crack

一个库&#xff0c;‍ 无限的UI选择&#xff0c;直接在您的应用程序中享受交互式流程图、BPMN 和其他图表工作室。利用我们的模板化应用程序&#xff0c;将开发时间缩短至几天。 经过十多年和数百万行代码的编写&#xff0c;我们推出了一组随时可用的功能&#xff0c;以帮助您创…

数据结构进阶 二叉树OJ题二

作者&#xff1a;小萌新 专栏&#xff1a;数据结构进阶 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;介绍几道二叉树的oj题 题目一 二叉搜索树与双向链表 输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的双向链表…

帆软—图表专题

饼图 优点&#xff1a;能很直观的看到每一个部分在整体中所占的比例。 缺点&#xff1a;不适合较大的数据集&#xff08;分类&#xff09;展现&#xff0c;数据项中不能有负值&#xff0c;当比例接近时&#xff0c;人眼很难准确判别。 变形饼图 柱形图 特点 优点&#xff…

SpringBoot HandlerMethodArgumentResolver接口自定义参数解析器

参考资料 【SpringBoot】HandlerMethodArgumentResolver的简单使用HandlerMethodArgumentResolver(参数解析器)的作用使用小案例HandlerMethodArgumentResolver用于统一获取当前登录用户 目录一. 需求二. 前期准备三. 实现HandlerMethodArgumentResolver接口四. 将自定义的方法…

一套javassf门户网站管理系统源码分享

淘源码&#xff1a;国内专业的免费源码下载平台 JAVA SSF项目框架源码 后台管理系统源码 一套以SpringMVCSpringHibernateFreemarkerShiroLuceneHtml5jQuery为技术核心架构的门户网站管理系统源码。 源码免费分享&#xff0c;需要源码学习可私信我。 主要功能&#xff1a; 内…

笑对过往、活在当下、期盼未来

哈喽大家好&#xff0c;我是阿Q。 去年今日&#xff0c;也是安静的午后&#xff0c;拿起铅笔在纸上寥寥草草的写下几个年终关键词&#xff0c;思索良久&#xff0c;迟迟未能下笔。 时至今日&#xff0c;年末将至&#xff0c;再次执笔已时隔一年&#xff0c;再不拿笔记录这转瞬…

Python制作粒子烟花,程序员的跨年姿势

跨年倒计时还有半天&#xff1f;我已经开始整烟花了&#xff0c;虽然不是很好看吧&#xff0c;但是也能将就看看 &#x1f625; 这个的背景图&#xff0c;音乐&#xff0c;还有文字都是可以自己修改的哦 效果展示 依次导入本次需要使用到的模块 import random import pygame…

免费的JPEG 恢复软件 - 照片删除了怎么恢复?

照片删除了怎么恢复? 照片在我们的生活中起着至关重要的作用&#xff0c;因为它们可以承载我们的快乐回忆&#xff0c;记录我们的日常生活&#xff0c;分享我们的快乐等。我们将在智能手机、相机或计算机上拍摄并存储大量 JPEG 图片。但是&#xff0c;无论我们多么小心地保留它…

Python和MySQL对比(2):用Pandas 实现MySQL的 union 和 join 语法效果

文章目录一、前言二、语法对比数据表unionjoin1、两表 inner join2、两表 left join3、两表 right join4、两表 outer join5、多表 join三、小结一、前言 环境&#xff1a; windows11 64位 Python3.9 MySQL8 pandas1.4.2 本文主要介绍 MySQL 中的union和join如何使用pandas实现…

Spring 核心概念 IOC/DI IOC容器 Bean

目录 一&#xff1a;代码书写现状 二&#xff1a;核心思想 一&#xff1a;代码书写现状 常规操作如上,但存在着问题,将项目上线后&#xff0c;需要将数据层进行更换,更换如下&#xff1a; 数据层更换后&#xff0c;业务层也需要进行更换&#xff0c;更换如下&#xff1a; 数据…

NLP学习笔记(五) 注意力机制

大家好&#xff0c;我是半虹&#xff0c;这篇文章来讲注意力机制 (Attention Mechanism) 在序列到序列模型中的应用 在上一篇文章中&#xff0c;我们介绍了序列到序列模型&#xff0c;其工作流程可以概括为以下两个步骤 首先&#xff0c;用编码器将输入序列编码成上下文向量&a…

费控产品之易快报洞察解析

1.费控行业洞察 1.1 概念及管理范畴界定 费控业务的本质是企业支出的管理&#xff0c;因此分析费控要从企业支出管理的宏观范畴来看&#xff0c;企业支出主要包括两方面&#xff0c;一个是企业成本&#xff0c;一个是期间费用。期间费用就是我们常说的管理费用、销售费用和财务…

Centos7的安装与模板机的制作

Centos7的安装与模板机的制作 1.安装环境准备 1.VMware Workstation 2.centos7镜像 本文用的VMware版本为16.2.1 build-18811642 2.开始安装 话不多说&#xff0c;直接上图 3.模板机制作 1.查看防火墙的运行状态 firewall-cmd --state防火墙目前正在启动中 2.关闭防火墙…

STM32——STM32简介与创建工程

文章目录一、stm32简介stm32MCU&#xff1a;ARM&#xff1a;命名规则&#xff1a;片上资源/外设&#xff1a;系统结构&#xff1a;引脚的定义功能引脚介绍&#xff1a;最小系统引脚介绍&#xff1a;电源引脚介绍&#xff1a;启动配置最小系统电路二、软件安装三、新建工程固件库…

2022年专业408的算法题

文章目录0 结果1 题目2 思路3 实现3.1 思路13.2 思路二0 结果 1 题目 2 思路 1&#xff0c;首先明确二叉搜索树的定义&#xff1a;任何一个节点大于其左子树中的全部结点&#xff0c;小于其右子树中的全部结点。中序遍历二叉搜索树得到一个升序序列。2&#xff0c;明确题目中给…