各类聚类算法整理

各类聚类算法整理

  • 0. 先验的基础知识
  • 1. K-Means
  • 2. GMM
  • 3. EM算法
  • 4.Spectral Clustering
  • 5. Mean Shift
  • 6. DBSCAN

本篇将介绍整理各种聚类算法,包括k-means,GMM(Guassian Mixture Models, 高斯混合),EM(Expectation Maximization,期望最大法),Spectral Clustering(谱聚类),Mean Shift(均值偏移)和DBSCAN(Density-Based Spatial Clustering of Applications with Noise)

0. 先验的基础知识

文章: 聚类算法的先验基础知识

1. K-Means

K-means算法是一种常用的聚类算法,用于将数据集中的样本分成 K 个不同的类别或簇。

  • 原理介绍:

    • 初始化: 随机选择 K 个初始聚类中心。
    • 分配样本: 将每个样本分配到距离最近的聚类中心所在的簇。
    • 更新中心: 对每个簇,计算其所有样本的均值,将该均值作为新的聚类中心。
    • 重复步骤2和步骤3,直到收敛: 当聚类中心不再变化或变化很小时,算法收敛,得到最终的聚类结果。
  • 优缺点:

    • 优点:
      • 简单直观,易于理解和实现。
      • 可以处理大规模数据集。
      • 对处理球形簇形状的数据效果较好。
    • 缺点:
      • 需要预先指定聚类个数 K。
      • 对异常值敏感,可能导致聚类结果不佳。
      • 结果可能收敛到局部最优解,因此多次运行可以获得更好的结果。
    • 应用:
      • 数据分析:对数据集进行聚类分析,发现数据集中的内在结构。
      • 图像处理:对图像像素进行聚类,实现图像分割和压缩。
      • 推荐系统:对用户进行聚类,提供个性化推荐。
  • C++代码:

#include <iostream>
#include <vector>
#include <cmath>
#include <limits>using namespace std;// 计算两个点之间的欧氏距离
double distance(vector<double>& point1, vector<double>& point2) {double sum = 0.0;for (int i = 0; i < point1.size(); ++i) {sum += pow(point1[i] - point2[i], 2);}return sqrt(sum);
}// 更新簇的中心
void updateCenters(vector<vector<double>>& points, vector<vector<double>>& centers, vector<int>& clusterAssignments) {vector<int> clusterCounts(centers.size(), 0);vector<vector<double>> newCenters(centers.size(), vector<double>(centers[0].size(), 0.0));for (int i = 0; i < points.size(); ++i) {int cluster = clusterAssignments[i];for (int j = 0; j < points[i].size(); ++j) {newCenters[cluster][j] += points[i][j];}clusterCounts[cluster]++;}for (int i = 0; i < newCenters.size(); ++i) {if (clusterCounts[i] > 0) {for (int j = 0; j < newCenters[i].size(); ++j) {newCenters[i][j] /= clusterCounts[i];}}}centers = newCenters;
}// K-means算法
void kMeans(vector<vector<double>>& points, int k, double threshold) {vector<vector<double>> centers(k);vector<int> clusterAssignments(points.size(), -1);// 随机初始化聚类中心for (int i = 0; i < k; ++i) {int randIndex = rand() % points.size();centers[i] = points[randIndex];}bool converged = false;while (!converged) {converged = true;// 分配样本到最近的聚类中心for (int i = 0; i < points.size(); ++i) {double minDist = numeric_limits<double>::max();int minIndex = -1;for (int j = 0; j < centers.size(); ++j) {double dist = distance(points[i], centers[j]);if (dist < minDist) {minDist = dist;minIndex = j;}}if (clusterAssignments[i] != minIndex) {converged = false;clusterAssignments[i] = minIndex;}}// 更新聚类中心if (!converged) {vector<vector<double>> oldCenters = centers;updateCenters(points, centers, clusterAssignments);// 判断中心点变化是否小于阈值double maxCenterShift = 0.0;for (int i = 0; i < centers.size(); ++i) {double shift = distance(oldCenters[i], centers[i]);if (shift > maxCenterShift) {maxCenterShift = shift;}}if (maxCenterShift < threshold) {converged = true; // 达到收敛条件}}}// 打印聚类结果for (int i = 0; i < points.size(); ++i) {cout << "Point " << i << " belongs to cluster " << clusterAssignments[i] << endl;}
}int main() {// 示例数据vector<vector<double>> points = {{1, 2}, {5, 6}, {3, 4}, {8, 9}, {7, 8}};int k = 2; // 聚类个数double threshold = 0.001; // 中心点位置变化阈值// 调用 K-means 算法kMeans(points, k, threshold);return 0;
}
  • 技巧:
    因为在更新中心点之前需要得到所有点所属的中心点,然后才能计算更新后的中心点。这样效率比较低,可以每次迭代只选择其中的一部分点来完成中心点的更新,这种做法叫做mini batch k_means。

2. GMM

高斯混合模型(Gaussian Mixture Model,GMM)是一种常用的概率模型,用于对数据进行聚类或密度估计。原理是基于假设:数据是由多个高斯分布组成的混合物。每个高斯分布代表一个聚类簇,而混合模型则将多个高斯分布加权组合起来,以适应数据中的不同分布情况。简单来说就是集合P中包含的所有点是来自多个分布的,但是现在想用所有分布的加权平均来表达集合P中所有点的分布。但是因为单一的高斯分布不明确,且加权平均权重也不明确,所以通过这组数据得到 K K K个不同的高斯分布以及 K K K个权重就是GMM聚类算法的核心。最后的聚类结果就是得到每个点属于每个高斯分布的后验概率,就完成了聚类。

说人话:有一组2维点,表示为 X = [ x 1 , x 2 , . . . , x n ] , x i ∈ R 2 X=[\mathbf{x}_1, \mathbf{x}_2, ...,\mathbf{x}_n],\mathbf{x}_i \in R_2 X=[x1,x2,...,xn]xiR2 x i \mathbf{x}_i xi表示第 i i i个点的坐标。这 n n n个点来自于 K K K个不同的高斯分布(也就是说这 n n n个点可以分成 K K K组,每组点都是从同一个分布中采样得到),但是我们得到的信息只有这组点的坐标,并不知道这K个高斯分布参数是多少。另外,K个单一的高斯分布对每个点的概率贡献权重也不知道。所以GMM的算法核心就是通过这组点的坐标信息得到 π , μ , Σ , π ∈ R 2 × k , μ ∈ R 2 × k , k = 1 , 2 , 3 , . . . , K \mathbf{\pi},\mu,\Sigma,\pi\in R_{2\times k}, \mu\in R_{2\times k} ,k=1,2,3,...,K π,μ,Σ,πR2×k,μR2×k,k=1,2,3,...,K Σ = [ Σ 1 , Σ 2 , . . . , Σ k ] , Σ i = d i a g ( σ i 1 2 , σ i 2 2 ) ; \Sigma = [\Sigma_1,\Sigma_2,...,\Sigma_k], \Sigma_i = diag(\sigma_{i1}^2,\sigma_{i2}^2); Σ=[Σ1,Σ2,...,Σk],Σi=diag(σi12,σi22);这里高斯分布的参数之所以都是2维的,是因为我们的点坐标是2维的,这里代表不同维度有不同的高斯分布参数,比如说颜色属性和坐标属性。

单维度变量 x x x的高斯分布,描述为:
N ( x ∣ μ , σ 2 ) = 1 ( 2 π σ 2 ) 1 2 e x p { − 1 2 σ 2 ( x − μ ) 2 } \mathcal{N}(x|\mu,\sigma^2) = {1 \over (2\pi\sigma^2)^{1\over2}} exp \{{-1\over2\sigma^2}(x-\mu)^2\} N(xμ,σ2)=(2πσ2)211exp{2σ21(xμ)2}

多维度变量 x , x ∈ R D \mathbf{x} ,\mathbf{x} \in R_D x,xRD的高斯公式,描述为:
N ( x ∣ μ , Σ ) = 1 ( 2 π ) D / 2 1 ∣ Σ ∣ 1 / 2 exp ⁡ { − 1 2 ( x − μ ) T Σ − 1 ( x − μ ) } \mathcal{N}(\mathbf{x} \mid \boldsymbol{\mu}, \boldsymbol{\Sigma})=\frac{1}{(2 \pi)^{D / 2}} \frac{1}{|\boldsymbol{\Sigma}|^{1 / 2}} \exp \left\{-\frac{1}{2}(\mathbf{x}-\boldsymbol{\mu})^{\mathrm{T}} \boldsymbol{\Sigma}^{-1}(\mathbf{x}-\boldsymbol{\mu})\right\} N(xμ,Σ)=(2π)D/21Σ1/21exp{21(xμ)TΣ1(xμ)}

高斯混合分布,公式表达为:
p ( x ) = ∑ k = = 1 K π k N ( x ∣ μ k , Σ k ) p(x) = \sum_{k==1}^K\pi_kN(x|\mu_k,\Sigma_k) p(x)=k==1KπkN(xμk,Σk)
公式表示了变量 x x x在高混合分布中的概率值。

  • 算法步骤

    • 初始化:选择初始均值 μ \mu μ、协方差矩阵 Σ \Sigma Σ和混合系数 π , μ = [ μ 1 , μ 2 , . . . , μ k ] , Σ = [ Σ 1 , Σ 2 , . . . , Σ k ] , π = [ π 1 , π 2 , . . . , π k ] , k = 1 , 2 , . . . , K \pi,\mu=[\mu_1,\mu_2,...,\mu_k],\Sigma=[\Sigma_1,\Sigma_2,...,\Sigma_k],\pi = [\pi_1,\pi_2,...,\pi_k],k=1,2,...,K π,μ=[μ1,μ2,...,μk],Σ=[Σ1,Σ2,...,Σk],π=[π1,π2,...,πk],k=1,2,...,K
    • EM算法:迭代进行E步(Expectation)和M步(Maximization)。在E步中,计算每个数据点 x \mathbf{x} x属于每个高斯分布的后验概率 P ( z k ∣ x ) , z k P(z_k|\mathbf{x}),z_k P(zkx),zk表示第 k k k个高斯分布。在M步中,利用这些后验概率更新高斯分布的参数 μ \mu μ Σ \Sigma Σ π \pi π
    • 收敛:当参数变化小于设定阈值或达到最大迭代次数时停止迭代。
  • E-Step,计算每个数据点 x x x属于每个高斯分布的后验概率 P ( z k ∣ x ) P(z_k|\mathbf{x}) P(zkx)
    γ n k ≡ p ( z k ∣ x n ) = π k p ( x n ∣ z k ) ∑ j = 1 K π j p ( x n ∣ z j ) = π k N ( x n ∣ μ k , Σ k ) ∑ j = 1 K π j N ( x n ∣ μ j , Σ j ) \begin{aligned} \gamma_{nk} \equiv p\left(z_k \mid \mathbf{x}_n\right) & =\frac{\pi_kp\left(\mathbf{x}_n \mid z_{k}\right)}{\sum_{j=1}^{K} \pi_j p\left(\mathbf{x}_n \mid z_{j}\right)} \\ & =\frac{\pi_{k} \mathcal{N}\left(\mathbf{x}_{n} \mid \mu_{k}, \Sigma_{k}\right)}{\sum_{j=1}^{K} \pi_{j} \mathcal{N}\left(\mathbf{x}_{n} \mid \mu_{j}, \Sigma_{j}\right)} \end{aligned} γnkp(zkxn)=j=1Kπjp(xnzj)πkp(xnzk)=j=1KπjN(xnμj,Σj)πkN(xnμk,Σk)
    r n k r_{nk} rnk表示第n个点属于第k个高斯分布的概率。

  • M-Step,使用E步求出的后验概率更新高斯分布的参数 μ \mu μ Σ \Sigma Σ π \pi π
    首先,需要明确的一点是,更新是需要等式的,那么 r n k r_{nk} rnk与三者的联系是什么,就需要进一步的求解推导。这里借助极大似然估计的思想,拉格朗日算子法的手段得到三者的联系。
    核心思想是寻找使得观测到的数据在给定模型下出现的可能性最大的参数值。即,选择使似然度函数 L ( μ , Σ , π ∣ x ) L(\mu,\Sigma,\pi|x) L(μ,Σ,πx)最大化的参数值 μ , Σ , π \mu,\Sigma,\pi μ,Σ,π。公式表达为:
    π , μ , Σ = arg ⁡ max ⁡ π , μ , Σ ln ⁡ p ( X ∣ π , μ , Σ ) = arg ⁡ max ⁡ π , μ , Σ ∑ n = 1 N ln ⁡ { ∑ k = 1 K π k N ( x n ∣ μ k , Σ k ) } , s . t . = ∑ k = 1 K π k = 1 \pi, \mu, \boldsymbol{\Sigma}=\underset{\pi, \mu, \boldsymbol{\Sigma}}{\arg \max } \ln p(\mathbf{X} \mid \pi, \mu, \boldsymbol{\Sigma})=\underset{\pi, \mu, \boldsymbol{\Sigma}}{\arg \max } \sum_{n=1}^{N} \ln \left\{\sum_{k=1}^{K} \pi_{k} \mathcal{N}\left(\mathbf{x}_{n} \mid \mu_{k}, \boldsymbol{\Sigma}_{k}\right)\right\},s.t.=\sum_{k=1}^{K} \pi_{k}=1 π,μ,Σ=π,μ,Σargmaxlnp(Xπ,μ,Σ)=π,μ,Σargmaxn=1Nln{k=1KπkN(xnμk,Σk)},s.t.=k=1Kπk=1

    • μ k \mu_k μk求偏导得,
      0 = − ∑ n = = 1 N γ n k Σ k ( x n − μ k ) μ k = 1 N k ∑ n = 1 N γ n k x n 0 = -\sum_{n==1}^N\gamma_{nk}\Sigma_k(\mathbf{x}_n-\mu_k) \\ \mu_k = {1\over N_k}\sum_{n=1}^N\gamma_{nk}\mathbf{x}_n 0=n==1NγnkΣk(xnμk)μk=Nk1n=1Nγnkxn
      其中, N k N_k Nk是后验概率之和,物理意义是表示有多少点是属于第k个高斯分布的, μ k \mu_k μk物理意义是属于第k个高斯分布的所有点的加权平均,不是平均值,还有权重

    • Σ k \Sigma_k Σk求偏导得,
      Σ k = 1 N k ∑ n − 1 N γ ( z n k ) ( x n − μ k ) ( x n − μ k ) T \Sigma_{k}=\frac{1}{N_{k}} \sum_{n-1}^{N} \gamma\left(z_{n k}\right)\left(\mathbf{x}_{n}-\mu_{k}\right)\left(\mathbf{x}_{n}-\mu_{k}\right)^{T} Σk=Nk1n1Nγ(znk)(xnμk)(xnμk)T

    • 对拉格朗日参数 λ \lambda λ求偏导得,这里结合拉格朗日算子法,目标函数为:
      ln ⁡ p ( X ∣ π , μ , Σ ) + λ ( ∑ k = 1 K π k − 1 ) ln ⁡ p ( X ∣ π , μ , Σ ) = ∑ n = 1 N ln ⁡ { π k N ( x n ∣ μ k , Σ k ) } \ln p(\mathbf{X} \mid \pi, \mu, \Sigma)+\lambda\left(\sum_{k=1}^{K} \pi_{k}-1\right) \\ \ln p(\mathbf{X} \mid \pi, \mu, \Sigma)=\sum_{n=1}^{N} \ln \left\{\pi_{k} \mathcal{N}\left(\mathbf{x}_{\mathbf{n}} \mid \mu_{k}, \Sigma_{k}\right)\right\} lnp(Xπ,μ,Σ)+λ(k=1Kπk1)lnp(Xπ,μ,Σ)=n=1Nln{πkN(xnμk,Σk)}
      得,
      λ = − N \lambda = -N λ=N

    • π k \pi_k πk求偏导得,
      π k = N k N \pi_k = {N_k \over N} πk=NNk
      其中N为所有点的数量

  • 代码部分

#include <iostream>
#include <vector>
#include <Eigen/Dense> // 使用Eigen库进行矩阵运算using namespace std;
using namespace Eigen;// 定义GMM模型参数
struct GMMParameters {vector<double> weights; // 每个高斯分布的权重vector<VectorXd> means; // 每个高斯分布的均值向量vector<MatrixXd> covariances; // 每个高斯分布的协方差矩阵
};// 计算高斯分布的概率密度
double gaussianPDF(VectorXd x, VectorXd mean, MatrixXd covariance) {int dim = x.size();double det = covariance.determinant();MatrixXd invCov = covariance.inverse();VectorXd diff = x - mean;double exponent = -0.5 * diff.transpose() * invCov * diff;double normalizer = pow(2 * M_PI, -dim / 2) * sqrt(det);return exp(exponent) / normalizer;
}// 对每个数据点计算属于每个高斯分布的后验概率
MatrixXd computePosterior(vector<VectorXd>& data, GMMParameters& params) {int numData = data.size();int numComponents = params.weights.size();MatrixXd posterior(numData, numComponents);for (int i = 0; i < numData; ++i) {VectorXd x = data[i];for (int j = 0; j < numComponents; ++j) {double likelihood = gaussianPDF(x, params.means[j], params.covariances[j]);posterior(i, j) = params.weights[j] * likelihood;}posterior.row(i) /= posterior.row(i).sum(); // 归一化后验概率}return posterior;
}// 更新GMM参数
void updateGMMParameters(vector<VectorXd>& data, MatrixXd& posterior, GMMParameters& params) {int numData = data.size();int numComponents = params.weights.size();VectorXd weights(numComponents);vector<VectorXd> means(numComponents);vector<MatrixXd> covariances(numComponents);// 更新每个高斯分布的权重、均值和协方差矩阵for (int j = 0; j < numComponents; ++j) {weights[j] = posterior.col(j).sum() / numData; // 更新权重VectorXd mean = VectorXd::Zero(data[0].size());for (int i = 0; i < numData; ++i) {mean += posterior(i, j) * data[i];}mean /= posterior.col(j).sum(); // 更新均值means[j] = mean;MatrixXd covariance = MatrixXd::Zero(data[0].size(), data[0].size());for (int i = 0; i < numData; ++i) {VectorXd diff = data[i] - mean;covariance += posterior(i, j) * (diff * diff.transpose());}covariance /= posterior.col(j).sum(); // 更新协方差矩阵covariances[j] = covariance;}// 更新参数params.weights = weights;params.means = means;params.covariances = covariances;
}int main() {// 生成示例数据vector<VectorXd> data;data.push_back(VectorXd(2));data[0] << 1, 2;data.push_back(VectorXd(2));data[1] << 3, 4;// 初始化GMM参数GMMParameters params;params.weights = {0.5, 0.5};params.means.push_back(VectorXd(2));params.means[0] << 1, 2;params.means.push_back(VectorXd(2));params.means[1] << 3, 4;params.covariances.push_back(MatrixXd::Identity(2, 2));params.covariances.push_back(MatrixXd::Identity(2, 2));// EM算法迭代更新参数for (int iter = 0; iter < 10; ++iter) {MatrixXd posterior = computePosterior(data, params);updateGMMParameters(data, posterior, params);}// 输出更新后的GMM参数cout << "Updated GMM Parameters:" << endl;cout << "Weights: " << params.weights[0] << ", " << params.weights[1] << endl;cout << "Mean 1: " << params.means[0].transpose() << endl;cout << "Mean 2: " << params.means[1].transpose() << endl;cout << "Covariance 1: " << endl << params.covariances[0] << endl;cout << "Covariance 2: " << endl << params.covariances[1] << endl;return 0;
}

3. EM算法

K-means和GMM算法都属于EM算法,EM算法的通用推导比较麻烦,就不再推导了。
实在是写不动了,先贴图吧,以后有空了编辑

在这里插入图片描述
在这里插入图片描述

4.Spectral Clustering

Spectral Clustering(谱聚类)是一种基于图论和谱理论的聚类算法,其原理、应用场景以及优缺点如下:

  • 原理步骤

    • 构建相似度图: 首先根据数据集中样本点之间的相似度构建一个相似度图(通常是无向加权图),其中节点表示样本点,边的权重表示样本点之间的相似度。
    • 计算拉普拉斯矩阵: 根据相似度图计算拉普拉斯矩阵(Laplacian Matrix)。常用的有度数矩阵(Degree Matrix)和邻接矩阵(Adjacency Matrix)构建拉普拉斯矩阵。
    • 特征值分解: 对拉普拉斯矩阵进行特征值分解,得到特征值和对应的特征向量。
    • 选取特征向量: 根据特征值和特征向量,选取其中特征值较小的前 k 个特征向量(k 为聚类簇的数量)。
    • 聚类: 利用选取的特征向量进行聚类,常用的方法包括 K-means 等聚类算法。
  • 应用场景

    • 图像分割: 在图像处理中,谱聚类可以用于图像分割,将图像中相似的像素点聚类到同一个分割区域。
    • 社交网络分析: 在社交网络分析中,可以利用谱聚类对用户进行聚类,发现社区结构或用户群体。
    • 模式识别: 在模式识别领域,谱聚类可用于将相似模式或特征聚类到一起,用于数据降维或分类。
    • 推荐系统: 在推荐系统中,可以利用谱聚类对用户或物品进行聚类,实现个性化推荐。
  • 优缺点

    • 优点:
  1. 对非线性、非凸分布的数据具有较好的适应性。
  2. 能够发现不规则形状的聚类簇。
  3. 对噪声数据较为鲁棒。
  • 缺点:
  1. 对于大规模数据集计算复杂度较高。
  2. 需要事先确定聚类簇的数量。
  3. 对于高维稀疏数据表现不佳。
  4. 总体来说,谱聚类算法在处理非线性、非凸分布的数据,发现不规则形状的聚类簇方面具有一定优势,但在大规模数据和
    高维稀疏数据上可能存在一些挑战。因此,在选择聚类算法时需要根据具体应用场景和数据特点进行综合考虑。

谱聚类关注的是连接性,并不是工作在欧式空间上
在这里插入图片描述

5. Mean Shift

一种基于密度的聚类算法

  1. 初始化
    从数据集中随机选择一个数据点作为初始的圆心。
    设定初始的圆半径 r r r
  2. 移动圆
    将圆移动到窗口内的数据点的中心位置。
    计算窗口内所有数据点的平均位置,将圆心移动到该位置。
  3. 收敛判断
    检查圆心移动的距离是否小于设定的阈值 ϵ ϵ ϵ,如果是则认为已经收敛,停止迭代。
    否则,继续迭代执行步骤2。
  4. 移除重叠圆
    如果存在重叠的圆,则保留包含数据点数量最多的圆,移除其他重叠的圆。
    对于重叠的圆,可以比较它们所包含的数据点数量来决定保留哪一个圆。
  5. 确定聚类中心
    使用保留的圆的圆心作为聚类中心。
    可以根据圆的圆心与数据点的距离来确定数据点所属的聚类。
  6. 重复步骤 1-5
    继续选择新的圆心并执行移动、收敛判断、移除重叠圆、确定聚类中心的步骤,直到所有圆都收敛且没有重叠。
    这种方法结合了Mean Shift的密度估计和圆的移动过程,通过移除重叠圆和确定聚类中心的方式来处理重叠的情况,并最终确定聚类结果。这样的方法可以更好地处理重叠的情况,并在一定程度上提高聚类的准确性。

6. DBSCAN

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法,它可以有效地处理具有任意形状和大小的聚类,并且能够识别和排除噪声数据点。

  • DBSCAN算法基于以下两个重要概念:

    • 核心点(Core Point): 在给定的半径 ϵ 内至少包含指定数量 MinPts 个数据点的点被认为是核心点。
    • 密度可达(Density Reachable): 如果点 P 在点 Q 的 ϵ 邻域内,并且点 Q 是核心点,则点 P 是密度可达于点 Q。
  • 详细步骤

    • 初始化: 设置参数 ϵ 和MinPts,以及数据集。
    • 核心点标记: 对于每个数据点,计算其 ϵ 邻域内的数据点数量,如果大于等于 MinPts,则将该点标记为核心点。
    • 密度可达性: 对于每个核心点,通过递归地检查其 ϵ 邻域内的点是否密度可达,将其加入到同一个簇中。
    • 噪声点处理: 将未被标记为核心点且不属于任何簇的点标记为噪声点。
    • 聚类结果: 最终,所有密度可达的点被划分为不同的簇,噪声点则被排除。
  • 优缺点

    • 优点:
      • 能够处理任意形状的聚类,对于密度不均匀的数据效果较好。
      • 能够识别和排除噪声点。
      • 不需要预先指定聚类数量。
    • 缺点:
      • 对参数 ϵ 和 MinPts 比较敏感,需要调优。
      • 在高维数据集上可能会失效,因为密度的定义在高维空间中变得模糊。
      • 对于密度差异较大的数据集,可能会产生较多的噪声点或者无法正确识别聚类

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

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

相关文章

C#基础知识总结

C语言、C和C#的区别 ✔ 面向对象编程&#xff08;OOP&#xff09;&#xff1a; C 是一种过程化的编程语言&#xff0c;它不直接支持面向对象编程。然而&#xff0c;C 是一种支持 OOP 的 C 的超集&#xff0c;它引入了类、对象、继承、多态等概念。C# 是完全面向对象的&#xff…

TCP三次握手过程及抓包分析

TCP三次握手过程 一、TCP分段格式二、TCP三次握手三、Wireshark抓包分析 一、TCP分段格式 二、TCP三次握手 三、Wireshark抓包分析

设计模式总结-组合模式

组合设计模式 模式动机模式定义模式结构组合模式实例与解析实例一&#xff1a;水果盘实例二&#xff1a;文件浏览 更复杂的组合总结 模式动机 对于树形结构&#xff0c;当容器对象&#xff08;如文件夹&#xff09;的某一个方法被调用时&#xff0c;将遍历整个树形结构&#x…

刷题之Leetcode27题(超级详细)

27. 移除元素 力扣题目链接(opens new window)https://leetcode.cn/problems/remove-element/ 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用…

一篇文章带你掌握二叉树(附带二叉树基本操作完整代码演示,和两种思路)

【本长内容】 1. 掌握树的基本概念 2. 掌握二叉树概念及特性 3. 掌握二叉树的基本操作 4. 完成二叉树相关的面试题练习 1. 树形结构 1.1 概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是…

Vue - 2( 10000 字 Vue 入门级教程)

一&#xff1a;Vue 1.1 绑定样式 1.1.1 绑定 class 样式 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>绑定样式</title><style>......</style><script type"text/javascript" src&…

基于java web的超市管理系统

摘要 随着社会经济的不断发展&#xff0c;人们的生活水平不断提高。越来越多的零售行业得到了快速的发展&#xff0c;以最常见的超市最为明显。零售行业繁荣的背后也随之带来了许多行业隐患&#xff0c;越来越激烈的行业竞争不断的要求经营者更加高要求的管理超市内部的整个供…

代码随想录第31天 | 455.分发饼干 、376. 摆动序列、53. 最大子序和

一、前言 参考文献&#xff1a;代码随想录 今天的内容是贪心算法&#xff0c;这个算法分为两个极端&#xff0c;一个极端是很简单&#xff0c;靠常识就可以解出来&#xff0c;另外一个是&#xff0c;你怎么想也想不出来&#xff0c;只能看题解的那种。 and 对第一天和第二天…

微信小程序上传到gitee

共三步 1、新建gitee仓库 点号&#xff0c;新建仓库&#xff0c;填入仓库信息新建即可 2、修改版本管理参数 微信开发者工具中点开版本管理&#xff0c;未初始化&#xff0c;需要先点初始化 接下来将设置中的通用、网络认证、远程3个部分的参数填写好 通用&#xff1a;核对…

DashOJ-8.奇偶统计

题目链接&#xff1a; 题目详情 - 奇偶统计 - DashOJ 思路&#xff1a; &#xff08;while循环加if分支语句&#xff09; 巧用死循环 while(1) 然后在里面第一句就判断输入的数字是否等于0 if(x0) &#xff0c;如果 等于0就直接break跳出循环 或者用 while(cin>>x) 代…

echarts 地图 自己圈地图 乡镇街道

这个是方式是我实在不愿意做的&#xff01; 如果有现成的最好&#xff0c;没有办法的情况下再用这个东西。 今天公司有一个项目&#xff0c;地方划分了一块区域&#xff0c;但是国家没有审核&#xff0c;但是项目里面用到了一个地图展示数据&#xff01;然后就需要我们自己把…

非conda环境(powershell与cmd)使用opencv-python库

1.安装python 3.11.7 Python Release Python 3.11.7 | Python.org 安装成功后,查看版本为3.11.7 2.安装numpy pip install numpy 3.安装matplotlib pip install matplotlib matplotlib库安装成功

k8s CNI Calico 网络模式总结

目录 calico架构图 IPIP模式下的架构图 calico 核心组件 Overlay 网络模式&#xff1a; Pod IP对外暴露 不对外暴露&#xff1a; 实现对外暴露的方法&#xff1a; overlay模式下的网络MTU Iptables & ipvs overlay的主要缺点&#xff1a; Full-mesh Unoverla…

【Linux】基础IO—1

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 先来段代码回顾C文件接口 "w"写文件 "a"追加文件 "r"读文件 输出信息到显示器&#xff0c;你有哪些方法 stdin & std…

Git入门实战教程之创建版本库

一、Git简介 Git是一个分布式版本控制系&#xff0c;分层结构如下&#xff1a; Git分为四层&#xff1a; 1、工作目录 当前正在工作的项目的实际文件目录&#xff0c;我们执行命令git init时所在的地方&#xff0c;也就是我们执行一切文件操作的地方。 2、暂存区 暂存区是…

Docker Compose从入门到熟悉

一、DockerCompose是什么&#xff1f; Compose 项目是 Docker 官方的开源项目&#xff0c;负责实现对 Docker 容器集群的快速编排。使用前面介绍的Dockerfile我们很容易定义一个单独的应用容器。然而在日常开发工作中&#xff0c;经常会碰到需要多个容器相互配合来完成某项任务…

栈的应用——用栈实现算数混合运算表达式的计算

1、单目运算符双目运算符 算数运算符分为单目运算符和双目运算符等 单目运算符只需要一个操作数,双目运算符需要两个操作数 双目运算符最常见:常见的算术运算符:*/,比较运算符:<>=等等以下是一些单目运算符:正号 (+): 用于表示正数或给数值一个正号。例如:+5 仍然…

基于卷积神经网络的土豆疾病识别系统(pytorch框架)【python源码+UI界面+前端界面+功能源码详解】

功能演示&#xff1a; 土豆疾病识别系统&#xff0c;基于vgg16&#xff0c;resnet50卷积神经网络&#xff08;pytorch框架&#xff09;_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于卷积神经网络的土豆疾病识别系统是在pytorch框架下实现的&#xff0c;系统中有两…

Linux | MySQL基础

MySQL MySQL是关系型数据库&#xff08;RDBMS&#xff09;&#xff0c;采用表格结构存储数据 同类型的还有Oracle、SQL Server 主要特点 适用于中小规模、关系型数据库系统(RDBMS) 支持Linux、Unix、Windows等多种操作系统 支持Python、Java、Perl、PHP等编程语言 典型应…

计组第三版书例题

基础知识过一下 存储器与CPU的连接主要通过数据总线、地址总线和控制总线实现。CPU首先向存储器发送地址信号&#xff0c;然后发出读写控制信号&#xff0c;最后在数据总线上进行数据的读写操作 。这种连接方式确保了CPU能够正确地访问和控制存储器中的数据。 https://blog.cs…