机器学习笔记之密度聚类——DBSCAN方法(Python代码实现)

news2025/2/26 22:01:03

机器学习笔记之密度聚类——DBSCAN方法[Python代码实现]

引言

本节将介绍密度聚类—— DBSCAN \text{DBSCAN} DBSCAN方法。

对于其他聚类任务的笔记:

  • K-Means \text{K-Means} K-Means聚类算法:传送门
  • 谱聚类算法 ( Spectral clustering ) (\text{Spectral clustering}) (Spectral clustering):传送门
  • 高斯混合模型 ( Gaussian Mixture Model,GMM ) (\text{Gaussian Mixture Model,GMM}) (Gaussian Mixture Model,GMM):传送门

基本思想

DBSCAN \text{DBSCAN} DBSCAN全称 Density-Based Spatial Clustering of Application with Noise \text{Density-Based Spatial Clustering of Application with Noise} Density-Based Spatial Clustering of Application with Noise。是一种基于密度聚类算法 ( Density-Based Clustering ) (\text{Density-Based Clustering}) (Density-Based Clustering)。而这里的密度是指样本分布的紧密程度。而密度聚类的思想假设:样本如果属于同一类别(),那么该类别内的样本点之间紧密相连

何为紧密相连 ? ? ?自然是指样本之间的距离足够小,小到没有办法将其划分给其他类别。我们通过找到一个初始位置后,通过查找与其紧密相连的样本,得到一个聚类簇;再次选择初始位置,反复执行上述操作,直到所有数据均有其归属为止。

概念介绍

DBSCAN \text{DBSCAN} DBSCAN既然属于聚类任务,说明它依然属于无监督学习任务的范畴。它一共包含两个参数

  • ϵ \epsilon ϵ:被称作邻域半径,它描述了某样本邻域的距离阈值;
  • MinPts \text{MinPts} MinPts:它描述了某样本,其距离为 ϵ \epsilon ϵ邻域中样本数量的阈值

给定数据集 D = { x ( i ) } i = 1 N ; x ( i ) ∈ R p \mathcal D = \{x^{(i)}\}_{i=1}^N;x^{(i)} \in \mathbb R^p D={x(i)}i=1N;x(i)Rp,对相关概念进行如下定义

  • ϵ \epsilon ϵ-邻域:它描述样本集合 D \mathcal D D中到某样本 x ( j ) ( j ∈ { 1 , 2 , ⋯   , N } ) x^{(j)}(j \in \{1,2,\cdots,N\}) x(j)(j{1,2,,N})距离不大于 ϵ \epsilon ϵ的样本 x ( i ) x^{(i)} x(i)组成的集合。使用 N ϵ ( x ( j ) ) \mathcal N_{\epsilon}(x^{(j)}) Nϵ(x(j))表示:
    样本间距离在 K-Means \text{K-Means} K-Means中介绍过‘明可夫斯基距离’ ( Minkowski Distance ) (\text{Minkowski Distance}) (Minkowski Distance)。其他的距离计算方式先挖一个坑,后续来填。
    N ϵ ( x ( i ) ) = { x ( i ) ∈ D ∣ Dist ( x ( i ) , x ( j ) ) ≤ ϵ } \mathcal N_{\epsilon}(x^{(i)}) = \{x^{(i)} \in \mathcal D \mid \text{Dist}(x^{(i)},x^{(j)}) \leq \epsilon\} Nϵ(x(i))={x(i)DDist(x(i),x(j))ϵ}
  • 核心对象 ( Core Object ) (\text{Core Object}) (Core Object):如果样本 x ( j ) x^{(j)} x(j) ϵ \epsilon ϵ-邻域内的样本数量 ∣ N ϵ ( x ( j ) ) ∣ ≥ MinPts |\mathcal N_{\epsilon}(x^{(j)})| \geq \text{MinPts} Nϵ(x(j))MinPts,那么称样本点 x ( j ) x^{(j)} x(j)是一个核心对象
    核心对象(红色样本点)
  • 密度直达 ( Directly Density-Reachable ) (\text{Directly Density-Reachable}) (Directly Density-Reachable):在样本点 x ( i ) x^{(i)} x(i)位于以 x ( j ) x^{(j)} x(j)核心对象 ϵ \epsilon ϵ-邻域内,则称 x ( i ) x^{(i)} x(i) x ( j ) x^{(j)} x(j)密度直达
    • 需要注意的是,这里包含一个由核心对象 x ( j ) x^{(j)} x(j)到ε-邻域内样本点 x ( i ) x^{(i)} x(i)的方向性,单向。
    • 密度直达不具备对称性。也就是说, x ( i ) x^{(i)} x(i) x ( j ) x^{(j)} x(j)密度直达,但 x ( j ) x^{(j)} x(j)不一定由 x ( i ) x^{(i)} x(i)密度直达。
      密度直达(示例)
  • 密度可达 ( Density-Reachable ) (\text{Density-Reachable}) (Density-Reachable):对于样本点 x ( i ) , x ( j ) x^{(i)},x^{(j)} x(i),x(j),如果存在样本序列 P 1 , P 2 , ⋯   , P n \mathcal P_1,\mathcal P_2,\cdots,\mathcal P_n P1,P2,,Pn,其中 P 1 = x ( j ) , P n = x ( i ) \mathcal P_1 = x^{(j)},\mathcal P_n = x^{(i)} P1=x(j),Pn=x(i),并且 P k + 1 \mathcal P_{k+1} Pk+1 P k ( k = 1 , 2 , ⋯   , n − 1 ) \mathcal P_k(k=1,2,\cdots,n-1) Pk(k=1,2,,n1)密度直达,则称 x ( i ) x^{(i)} x(i) x ( j ) x^{(j)} x(j)密度可达
    • 密度可达具有直递性。也就是说,如果 x ( i ) x^{(i)} x(i) x ( j ) x^{(j)} x(j)密度可达, x ( k ) x^{(k)} x(k) x ( i ) x^{(i)} x(i)密度可达,那么 x ( k ) x^{(k)} x(k) x ( j ) x^{(j)} x(j)密度可达
    • 密度可达同样不具备对称性。从明可夫斯基距离的角度解释对称性,文章见下方链接。如果使用 3 3 3阶明可夫斯基距离( L 3 L_3 L3范数)来描述样本点之间的距离:
      Dist ( x ( i ) , x ( j ) ) = ∑ k = 1 p ∣ x k ( i ) − x k ( j ) ∣ 3 3 = ∣ ∣ x ( i ) − x ( j ) ∣ ∣ 3 \text{Dist}(x^{(i)},x^{(j)}) = \sqrt[3]{\sum_{k=1}^{p}|x_k^{(i)} - x_k^{(j)}|^3} = ||x^{(i)} - x^{(j)}||_3 Dist(x(i),x(j))=3k=1pxk(i)xk(j)3 =∣∣x(i)x(j)3
      那么可能出现根号内的项 ∑ k = 1 p ∣ x k ( i ) − x k ( j ) ∣ 3 \begin{aligned}\sum_{k=1}^p |x_k^{(i)} - x_k^{(j)}|^3\end{aligned} k=1pxk(i)xk(j)3是一个负值,从而产生一个‘负距离’;相反,如果 ∑ k = 1 p ∣ x k ( j ) − x k ( i ) ∣ 3 \begin{aligned}\sum_{k=1}^p |x_k^{(j)} - x_k^{(i)}|^3\end{aligned} k=1pxk(j)xk(i)3结果是一个‘正距离’,最终导致 Dist ( x ( i ) , x ( j ) ) ≠ Dist ( x ( j ) , x ( i ) ) \text{Dist}(x^{(i)},x^{(j)}) \neq \text{Dist}(x^{(j)},x^{(i)}) Dist(x(i),x(j))=Dist(x(j),x(i))
      密度可达
  • 密度相连 ( Density-Connected ) (\text{Density-Connected}) (Density-Connected):对于样本点 x ( i ) , x ( j ) x^{(i)},x^{(j)} x(i),x(j),若存在样本点 x ( k ) x^{(k)} x(k),使得 x ( i ) , x ( j ) x^{(i)},x^{(j)} x(i),x(j)均由 x ( k ) x^{(k)} x(k)密度可达,则称 x ( i ) , x ( j ) x^{(i)},x^{(j)} x(i),x(j)密度相连
    • 需要注意的是,密度相连指的是 x ( i ) , x ( j ) x^{(i)},x^{(j)} x(i),x(j)之间的关系, x ( k ) x^{(k)} x(k)仅是一个媒介。
    • 密度相连关系满足对称性。也就是说, x ( i ) , x ( j ) x^{(i)},x^{(j)} x(i),x(j)之间的关系是无向的。
      密度相连(示例)

基于上述概念, DBSCAN \text{DBSCAN} DBSCAN对于的概念定义为:最大的密度相连样本集合。对于某个簇 C \mathcal C C,它包含如下属性:

  • 连接性: C \mathcal C C中的任意两个样本点之间密度相连
  • 最大性:已知样本点 x ( i ) ∈ C ⇒ x^{(i)} \in \mathcal C \Rightarrow x(i)C任意由 x ( i ) x^{(i)} x(i)密度可达的样本点均 ∈ C \in \mathcal C C

算法过程

整个 DBSCAN \text{DBSCAN} DBSCAN算法的核心在于:找到满足上述两种性质的。这个的表示为:核心对象 x x x密度可达的所有样本组成的集合
这个集合中自然也可能包含其他的‘核心对象’,并且该集合内任意两个样本之间均‘密度相连’。

X = { x ′ ∈ D ∣ x ⇒ x ′ ( Density-Reachable ) } \mathcal X = \{x' \in \mathcal D \mid x \Rightarrow x'(\text{Density-Reachable})\} X={xDxx(Density-Reachable)}
因此,该算法主要包括两个部分

  • 基于超参数:邻域半径 ϵ \epsilon ϵ;邻域内样本数量阈值 MinPts \text{MinPts} MinPts,找出数据集 D \mathcal D D内部所有的核心对象,最终构成核心对象集合 Ω \Omega Ω
  • 以任一核心对象为出发点,找出其所有密度可达的样本,构成;直到所有核心对象均被访问为止。
    需要注意的是,算法的迭代结束方式是‘所有核心对象被访问,而不是 D \mathcal D D中所有样本。数据集’ D \mathcal D D中不属于任何簇的样本被认为是‘噪声’ ( Noise ) (\text{Noise}) (Noise)或者‘异常’ ( Anomaly ) (\text{Anomaly}) (Anomaly)样本。

完整算法描述

输入部分:

  • 数据集 D = { x ( i ) } i = 1 N \mathcal D = \{x^{(i)}\}_{i=1}^N D={x(i)}i=1N
  • 参数:邻域半径 ϵ \epsilon ϵ;样本数量阈值 MinPts \text{MinPts} MinPts

核心对象查找:

  • 初始化核心对象集合 Ω = ∅ \Omega = \emptyset Ω=
  • 对每一个样本点 x ( j ) ( j = 1 , 2 , ⋯   , N ) x^{(j)}(j=1,2,\cdots,N) x(j)(j=1,2,,N)进行遍历:
  • \quad 计算样本点 x ( j ) x^{(j)} x(j) ϵ \epsilon ϵ-邻域 N ϵ ( x ( j ) ) \mathcal N_{\epsilon}(x^{(j)}) Nϵ(x(j))
  • \quad 判断邻域样本数量 ∣ N ϵ ( x ( j ) ) ∣ |\mathcal N_{\epsilon}(x^{(j)})| Nϵ(x(j))阈值 MinPts \text{MinPts} MinPts之间的大小关系;
    • ∣ N ϵ ( x ( j ) ) ∣ ≥ MinPts ⇒ x ( j ) |\mathcal N_{\epsilon}(x^{(j)})| \geq \text{MinPts} \Rightarrow x^{(j)} Nϵ(x(j))MinPtsx(j)核心对象,加入 Ω \Omega Ω集合中: Ω = Ω ∪ { x ( j ) } \Omega = \Omega \cup \{x^{(j)}\} Ω=Ω{x(j)}
    • 不是核心对象的样本点, Continue \text{Continue} Continue即可。
  • 最终返回核心对象集合 Ω \Omega Ω

寻找最大簇的过程

  • 聚类数初始化: k = 0 k=0 k=0
  • 未访问的样本集合: Γ = D \Gamma = \mathcal D Γ=D
  • 核心对象集合 Ω ≠ ∅ \Omega \neq \emptyset Ω=的条件下,执行如下迭代过程
  • \quad 记录当前迭代下,未访问的样本集合 Γ o l d = Γ \Gamma_{old} = \Gamma Γold=Γ
  • \quad 核心对象集合 Ω \Omega Ω中随机选取一个核心对象 o o o,初始化队列 Q = < o > \mathcal Q = <o> Q=<o>
  • \quad 与此同时,将核心对象 o o o Γ \Gamma Γ中去除 Γ = Γ \ { o } \Gamma = \Gamma \backslash \{o\} Γ=Γ\{o}
    \quad 即将对核心对象 o o o的所有密度可达样本进行发掘。反斜杠 \ \backslash \表示集合之间的相对差集。
    • 队列 Q ≠ ∅ \mathcal Q \neq \emptyset Q=条件下,执行如下迭代过程:
      如果 Q = ∅ \mathcal Q = \emptyset Q=,这意味着与核心对象 o o o密度可达的所有样本均被找到。这里也有可能包含其他的核心对象。

    • \quad 取出队列中的首个样本 q q q,并判别该样本点是否为核心对象
      这个队列中,初始化是一个随机的‘核心对象‘ o o o,但队列中存储的是与 o o o密度可达的所有样本点。我们需要从这些样本点里找出‘核心对象’,从而使其继续扩张、延伸。
      如果 ∣ N ϵ ( q ) ∣ ≥ MinPts |\mathcal N_{\epsilon}(q)| \geq \text{MinPts} Nϵ(q)MinPts,这意味着 q q q核心对象,并找出 q q q ϵ \epsilon ϵ-邻域 N ϵ ( q ) \mathcal N_{\epsilon}(q) Nϵ(q)未访问样本 Γ \Gamma Γ之间的重合样本 Δ \Delta Δ Δ = N ϵ ( q ) ∩ Γ \Delta = \mathcal N_{\epsilon}(q) \cap \Gamma Δ=Nϵ(q)Γ,并将这些样本 Δ \Delta Δ重新放回至队列 Q \mathcal Q Q中(在放回同时,将 Γ \Gamma Γ中的相应样本一并消除 Γ = Γ \ Δ \Gamma = \Gamma \backslash \Delta Γ=Γ\Δ)。

    • 持续迭代下去,当 Q \mathcal Q Q中没有元素时(子循环迭代结束),意味着这个最大簇中的样本已全部找全。与此同时, Γ \Gamma Γ中的样本已经减少了 Γ o l d − Γ \Gamma_{old} - \Gamma ΓoldΓ,也就是 C k \mathcal C_k Ck的样本数量:
      C k = Γ o l d \ Γ \mathcal C_k = \Gamma_{old} \backslash \Gamma Ck=Γold

  • 本次迭代最后,将 C k \mathcal C_k Ck中的所有核心对象 Ω \Omega Ω全部消除。也就是说,重新从剩余核心对象中找出最大簇
    Ω = Ω \ C k \Omega = \Omega \backslash \mathcal C_k Ω=Ω\Ck
  • 最终可得到一系列簇的结果: { C 1 , C 2 , ⋯   , C k } \{\mathcal C_1,\mathcal C_2,\cdots,\mathcal C_k\} {C1,C2,,Ck}

DBSCAN \text{DBSCAN} DBSCAN的优点和缺陷

  • 优点
    K-Means \text{K-Means} K-Means算法比较, DBSCAN \text{DBSCAN} DBSCAN不需要人为输入簇的数量 k k k;并且它可以找出任意聚类形状。而 K-Means \text{K-Means} K-Means高斯混合模型它们仅能针对于凸集合的样本聚类。

    DBSCAN \text{DBSCAN} DBSCAN迭代结束后,未访问集合 Γ \Gamma Γ可能会剩下一些点。这意味着,剩下的点不属于任何聚类簇(噪声、异常)。从这个角度可以看出,在聚类过程可以发现异常样本,并且对其不敏感。

    DBSCAN \text{DBSCAN} DBSCAN在初始化时选择核心对象作为初始迭代,而不是随机选择一点。这意味着 DBSCAN \text{DBSCAN} DBSCAN算法的鲁棒性很强,不会因初始样本对聚类结果产生巨大影响。

  • 缺陷
    如果出现类间差距较大,或者样本集密度不均匀,此时的 DBSCAN \text{DBSCAN} DBSCAN聚类效果较差。

    它的时间复杂度是不低的。随着样本数量的增加,导致算法收敛时间较长。

    虽然不用人为选择簇的数量,但关于 ϵ , MinPts \epsilon,\text{MinPts} ϵ,MinPts的调节过程是较复杂的。不同的参数组合方式对聚类效果(模型的过拟合、欠拟合)均存在较大影响。

2023/4/25 \text{2023/4/25} 2023/4/25补充:基于 Python \text{Python} Python的代码实现

基于二维特征的数据集分布表示如下:

from sklearn import datasets

NSamples = 150
(DToken,DLabel) = datasets.make_moons(n_samples=NSamples, noise=0.05)

对应的图像结果表示为:

  • 基于‘密度聚类’的特性,该算法更适合‘链条状’,并且分布均匀的样本集合。
  • 针对聚类任务,这里仅使用 DToken \text{DToken} DToken信息。
    原始样本分布

DBSCAN \text{DBSCAN} DBSCAN聚类算法代码表示如下:

import matplotlib.pyplot as plt
import numpy as np
import random
import math
from queue import Queue
from sklearn import datasets

# NSamples = 100
NSamples = 150
np.random.seed(42)
(DToken,DLabel) = datasets.make_moons(n_samples=NSamples, noise=0.05)


def DrawTestPic(D):

    for (x,y) in D:
        plt.scatter(x,y,c="tab:blue",s=4)
    plt.show()


def DBSCAN(Data,Epsilon,MinPts):

    def CalDistance(Sample1, Sample2):
        """
        Calculate Euclidean distance of Sample1 and Sample2.
        :return:Distance result
        """
        return math.sqrt(((Sample1[0] - Sample2[0]) ** 2) + (Sample1[1] - Sample2[1]) ** 2)

    def GetEpsilonNeighborhood(SamplePoint, Data, Epsilon):
        """
        The simplest way to find,We can use KD-Tree to reduce TimeComplexity.
        :param Sample: SamplePoint
        :return: Epsilon neighborhood of SamplePoint.
        """
        EpsilonNeighList = list()
        for K in Data:
            if tuple(K) == tuple(SamplePoint):
                continue
            else:
                DistKSamplePoint = CalDistance(K, SamplePoint)
                if DistKSamplePoint < Epsilon:
                    EpsilonNeighList.append(tuple(K))
                    
        return EpsilonNeighList

    def DiscrimCoreObject(Data,Epsilon,MinPts):
        """
        Get list of core object.
        :return: CoreObjectList.
        """
        CoreObjectList = list()
        for Sample in Data:
            EpsilonNeighList = GetEpsilonNeighborhood(Sample,Data,Epsilon)
            if len(EpsilonNeighList) >= MinPts:
                CoreObjectList.append(tuple(Sample))

        return CoreObjectList

    def ExecutiveProcess(Data,CoreObjectList):

        def CalRelDifferenceSet(List1,List2):
            """
            Calculate Relative Difference Set of List1 and List2
            :return:
            """
            return list(set(List1).difference(set(List2)))

        def CalIntersection(List1,List2):
            """
            Calculate Intersection Set of List1 and List2.
            :return:
            """
            return list(set(List1).intersection(set(List2)))

        ClusterNum = 0
        ClusterList = list()

        Gamma = [tuple(i) for i in Data.tolist()]
        while CoreObjectList:
            GammaOld = [tuple(i) for i in Gamma]
            RandomIndex = random.randint(0,len(CoreObjectList) - 1)
            RandomCoreObject = CoreObjectList[RandomIndex]
            Q = Queue()
            Q.put(RandomCoreObject)
            Gamma = CalRelDifferenceSet(Gamma,[RandomCoreObject])

            while not Q.empty():
                FirstElem = Q.get()
                EpsilonNeighborL = GetEpsilonNeighborhood(FirstElem,Data,Epsilon)
                if len(EpsilonNeighborL) >= MinPts:
                    Delta = CalIntersection(EpsilonNeighborL,Gamma)
                    for Elem in Delta:
                        Q.put(Elem)
                    Gamma = CalRelDifferenceSet(Gamma,Delta)

            NewCluster = CalRelDifferenceSet(GammaOld,Gamma)
            ClusterList.append(NewCluster)
            CoreObjectList = CalRelDifferenceSet(CoreObjectList,NewCluster)
            ClusterNum += 1

        return ClusterNum,ClusterList

    def PaintCluster(ClusterList):
        ColorList = ["tab:blue","tab:orange","tab:green","tab:red","tab:purple",
                     "tab:brown","tab:pink","tab:gray","tab:olive","tab:cyan"]
        for idx,Cluster in enumerate(ClusterList):
            for (x1,x2) in Cluster:
                plt.scatter(x1,x2,s=4,c=ColorList[idx])
        plt.show()

    ClusterNum,ClusterList = ExecutiveProcess(Data, DiscrimCoreObject(Data, Epsilon, MinPts))
    print(ClusterNum)
    return PaintCluster(ClusterList)

这里已经事先调整好了一组 Epsilon,MinPts \text{Epsilon,MinPts} Epsilon,MinPts参数:

if __name__ == '__main__':
	# Check Original Distribution.
	# DrawTestPic(DToken)
    # Two Clusters(standard).
    DBSCAN(DToken,Epsilon=0.2,MinPts=3)

聚类结果表示如下:
正确聚类结果
我们再观察另一组 Epsilon,MinPts \text{Epsilon,MinPts} Epsilon,MinPts参数:

if __name__ == '__main__':
    # 6 Clusters.
    DBSCAN(DToken, Epsilon=0.13, MinPts=3)

对应聚类结果返回如下:
6聚类-聚类结果
很明显,由于 ϵ \epsilon ϵ-邻域过小,导致本该属于同一聚类的样本分段了。这明显是过拟合 ( Over-Fitting ) (\text{Over-Fitting}) (Over-Fitting)
ϵ \epsilon ϵ-邻域过小,就是‘模型过于复杂’的一种体现。

这种描述范围的思想和 K \mathcal K K近邻算法之间存在异曲同工之妙

  • K \mathcal K K近邻是监督学习,标签都是已知的,仅需要描述范围内的样本数量的分类,再进行比较即可。
  • DBSCAN \text{DBSCAN} DBSCAN不仅需要设置邻域内样本数量阈值,还要设置邻域半径。它们之间共同点是:都要找最近邻的点。从而通过 KD \text{KD} KD对样本空间进行划分,这种最近邻样本点查找方式也是不错的选择。

相关参考:
DBSCAN 聚类算法详解
机器学习其中复习
《机器学习》(周志华著) 9.5 密度聚类

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

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

相关文章

【MySQL】索引与事务

索引&#xff1a; 什么是索引&#xff1f;为什么要⽤索引 为了提高查询效率而使用的一种数据结构把数据组织起来&#xff1b; 例如生活中的字典&#xff1a;声母&#xff0c;韵母&#xff0c;声调。 创建索引&#xff1a;自动创建的主键约束&#xff0c;唯一约束&#xf…

qiankun-微前端

项目结构 主应用&#xff1a; vue3 vite 子应用1&#xff1a;vue3 vite 背景介绍 项目采用了vue3vite构建的&#xff0c;又因为qiankun不支持vite&#xff0c;所以需要引用 vite-plugin-qiankun 插件来解决 主应用–改造 安装 qiankun npm install qiankun重新定义一个…

浅浅入门SpringBoot之Thymeleaf模板

Thymeleaf是一个流行的模板引擎,该模板引擎采用Java语言开发模板引擎是一个技术名词,是跨领域跨平台的概念,在Java语言体系下有模板引擎,在C#、PHP语言体系下也有模板引擎,甚至在 Javascript中也会用到模板引擎技术,Java生态下的模板引擎有 Thymeleaf、 Freemaker、Ⅴ elocity、…

【EMQX】EMQX管理控制台即EMQX Dashboard简介

EMQX管理控制台 一、EMQX Dashboard简介二、主要功能2.1 监控和管理 EMQX 集群中的相关信息与数据2.2 访问控制&#xff08;认证与授权&#xff09;管理2.3 数据集成2.4 在线配置热更新2.5 管理系统扩展能力2.6 全面的诊断工具 三、启动3.1 首次登录3.2 忘记密码 四、配置 Dash…

我老板:你根本不懂 React!

前言 我已经使用 React 多年&#xff0c;我确信我非常了解它&#xff0c;但最近我的老板对我说&#xff0c;“你根本不知道 React&#xff0c;你对它一无所知。” 我很生他的气&#xff0c;但他指出了我程序中的三个漏洞。我现在把它记录下来&#xff0c;也分享给还不知道的小…

用好ChatGPT,毕业直接走上人生巅峰

毕业论文交上去了&#xff0c;学分也攒齐了。考研没上岸的准毕业生们接下来要面对的不是惨烈的秋招&#xff0c;就是蹲家准备二战。生活终于要对各位小可爱们动手啦&#xff01; 不想默默承受社会的毒打&#xff1f; 不愿在屡战屡败屡败屡战的压力下秃头&#xff1f; 想必各位…

API 都有这些功能,你真的都知道么?

API&#xff08;应用程序编程接口&#xff09;可以提供以下功能&#xff1a; 数据传输&#xff1a;API可以在应用程序之间传输数据&#xff0c;包括发送和获取数据、更新数据等。 访问功能: API 可以调用另一个系统或应用程序的某些功能&#xff0c;例如获取天气&#xff0c;查…

基于无线传感器网络(WSN) 查找两个节点之间的最短路径并发送数据(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 本代码基于无线传感器网络&#xff0c;在两个节点&#xff08;源节点和目标节点&#xff09;之间找到最短路径&#xff0c;并开…

Java学习过程(韩顺平661-665)

网络通信是指在计算机网络中&#xff0c;通过网络连接的设备之间进行数据交换的过程。网络通信可以分为两种类型&#xff1a;有线网络通信和无线网络通信。 有线网络通信主要通过物理介质&#xff08;如光纤、双绞线等&#xff09;来传输数据&#xff0c;其中最常用的协议是以…

数字孪生新能源智慧充电桩Web3D可视化运维系统

放眼全球&#xff0c;近十年来&#xff0c;新能源汽车赛道堪称“热得发烫”。伴随着进入成年期的新能源汽车行业对相关配套设备支撑水平的提升&#xff0c;作为其“新基建”的充电桩领域表现更为突出的价值势能。过去&#xff0c;在一系列补贴政策和资本刺激下&#xff0c;充电…

七种MOS管栅极驱动电路

01 直接驱动 首先说一下电源IC直接驱动&#xff0c;下图是我们最常用的直接驱动方式&#xff0c;在这类方式中&#xff0c;我们由于驱动电路未做过多处理&#xff0c;因此我们进行PCB LAYOUT时要尽量进行优化。如缩短IC至MOSFET的栅极走线长度&#xff0c;增加走线宽度&#x…

《商用密码应用与安全性评估》第三章商用密码标准与产品应用3.4商用密码标准与产品

一、智能IC卡标准与产品 智能IC卡的分类 存储器卡&#xff1a;内部一般不包含密码安全机制&#xff0c;不具备信息处理能力&#xff0c;外部可对片内信息任意存取&#xff0c;因此存储器卡一般用于存放不需要保密的信息逻辑加密卡&#xff1a;逻辑加密卡内除了具有非易失性存…

redis缓存生产实践(一)---大key压缩

文章目录 前言一、缓存到底是使用String还是hash我该如何选择二、什么是大key及其影响2.1 什么是 Redis 大 key&#xff1f;2.2 大key带来的影响 三、大key压缩3.1 注解标记可能需要压缩的数据3.2 获取注解信息判断内存占用大小3.2 判断对象占用内存3.2 gzip压缩json3.2 判断当…

Reid之损失函数理论学习讲解

基于深度学习的Reid主要流程为输入图像-->CNN(提取特征)-->Global average pooling-->特征向量&#xff0c;将用这些特征来衡量图像的相似情况。并用这些特征进行检索&#xff0c;返回分类情况。 在训练网络的时候需要涉及损失函数&#xff0c;因此就引出了表征学习和…

大数据专业好找工作么

现在&#xff0c;在数字化转型的推动下&#xff0c;越来越多的企业意识到大数据的魅力&#xff0c;并不断在这个领域投入资金&#xff0c;Python大数据开发相关人才也备受青睐&#xff01; 学Python之前&#xff1a;这玩意真有传说中那么好么&#xff1f; 学Python之后&#…

【browser】浏览器跨域处理

好久没有更新博客了&#xff0c;前段时间在疯狂面试&#xff0c;最近工作了才有时间来写博客。 准备来讲讲面试里常问到的跨域处理吧。 说到跨域&#xff0c;我们可能会下意思的说出jsonp&#xff0c;服务端配置cors&#xff0c;node配置代理等&#xff0c;再多了&#xff0c;我…

加密脱胎于去中心化理想,但力求合规 细数各国政府态度之演变

比特币诞生之始&#xff0c;只是极客文化圈内流行的小众货币。如今&#xff0c;加密市场已经发展到无法忽视的程度&#xff0c;虽然全球仍未对加密货币形成共识&#xff0c;但监管已成为各国政府不得不考虑的问题。 美国&#xff1a;监管愈发模糊且不可测 美国始终是加密领域全…

八股文(Mybatis)

文章目录 1. Mybatis缓存机制2. 动态SQL语句3. 分页3. 1 几种分页方式3.2 MyBatis 是如何进行分页的&#xff1f;分页插件的原理是什么&#xff1f;3.3 逻辑分页和物理分页 1. Mybatis缓存机制 作用&#xff1a;避免每次都去查db 一级缓存是SqlSession级别的缓存&#xff0c;也…

Mysql统计分组后每组数据与每组数量区别

下边统计的是分组后每组的数量&#xff1a;结果是多个 select p.id (count(*)) from p group by p.id 如果想统计分组后&#xff0c;有多个分组&#xff0c;需要如下执行&#xff1a; select count(*) from (select p.id (count(*)) from p group by p.id) as a 此外&#xf…