[Python] 什么是KMeans聚类算法以及scikit-learn中的KMeans使用案例

news2024/11/29 0:38:51

什么是无监督学习?

无监督学习是机器学习中的一种方法,其主要目的是从无标签的数据集中发现隐藏的模式、结构或者规律。在无监督学习中,算法不依赖于任何先验的标签信息,而是根据数据本身的特征和规律进行学习和推断。无监督学习通常用于聚类、降维、异常检测等任务。在聚类中,算法会将相似的数据点归为一类;在降维中,算法会将高维数据映射到低维空间;在异常检测中,算法会发现与其他数据不同的离群点。无监督学习是与有监督学习相对应的,有监督学习则是依赖已知的标签信息进行学习和预测。

什么是聚类算法?

聚类算法是一种无监督学习方法,它将数据集中的对象按照相似性进行分组,即将相似的对象归为一类,不相似的对象归为不同的类别。聚类算法的目标是使得同一类内的对象相似度较高,而不同类之间的相似度较低。

聚类算法的一般步骤包括:

  1. 选择合适的相似性度量指标,常用的有欧氏距离、余弦相似度等。

  2. 初始化聚类中心,可以是随机选择数据集中的点或者通过其他方法来选择。

  3. 对每个数据点,计算其与聚类中心的相似度,并将其分配到最相似的聚类中心所在的类别。

  4. 根据已分配的数据点,更新聚类中心的位置,可以采用均值、中位数等方法。

  5. 重复步骤3和步骤4,直到达到某个停止条件,如收敛或达到最大迭代次数。

常见的聚类算法包括K-means、层次聚类、DBSCAN等。这些算法都有各自的特点和适用范围,需要根据具体的问题和数据来选择合适的算法。

聚类和分类算法的比较

聚类和分类是机器学习中常用的两种数据分析方法,它们在目标、方法和应用方面有一些区别。

目标:

  • 聚类的目标是将数据集中的对象划分为不同的组或类别,使得同一组内的对象相似度较高,不同组之间的相似度较低。聚类的目标是无监督的,即不依赖于已知的标签或类别信息。
  • 分类的目标是将数据对象划分到预定义的类别中,也称为标签或类别预测。分类的目标是有监督的,即依赖于已知的标签或类别信息。

方法:

  • 聚类方法通常是基于数据之间的相似度或距离来进行划分,常用的聚类方法有K-means、层次聚类、DBSCAN等。聚类方法通常不需要预先定义类别,而是通过计算数据之间的相似度来自动划分。
  • 分类方法则是基于已知的类别信息和训练数据来构建一个分类模型,可以使用各种分类算法,如决策树、支持向量机、逻辑回归等。分类模型利用训练数据的特征和对应的类别标签来学习并预测新数据的类别归属。

应用:

  • 聚类方法常用于数据探索、模式发现和相似性分析等领域。聚类可以帮助识别数据中潜在的群组或模式,发现数据的内在结构。
  • 分类方法常用于分类预测、图像识别、文本分类等应用。分类可以将新的数据对象归类到已知的类别中,进行预测和判断。

需要注意的是,聚类和分类并不是完全互斥的方法,有些应用场景中,聚类结果可以作为分类的一种辅助工具,帮助确定类别或构建分类模型。同时,聚类和分类方法的选择也取决于问题的特点、数据的性质和可用的标签信息。

什么是K-means聚类算法?

K-means聚类算法是一种常见且简单的聚类算法,它将数据集中的对象根据欧氏距离划分为K个不同的类别。其基本思想是通过迭代的方式,不断调整每个类别的中心位置,使得同一类别内的数据点到其中心的距离最小。

K-means聚类算法的步骤如下:

  1. 随机选择K个聚类中心点,可以是从数据集中随机选择或者通过其他方法确定。

  2. 对于每个数据点,计算其与每个聚类中心的距离,并将其分配到距离最近的聚类中心所在的类别。

  3. 根据已分配的数据点,更新每个类别的聚类中心位置,通常是计算该类别内所有数据点的均值。

  4. 重复步骤2和步骤3,直到达到某个停止条件,如类别内的数据点不再发生变化或达到最大迭代次数。

K-means算法的优点是简单且易于理解,计算效率高。然而,K-means算法对初始聚类中心的选择比较敏感,可能会陷入局部最优解。此外,K-means算法要求数据点之间的距离度量要有意义,且每个类别的大小相对均衡。对于非球形的聚类结构,K-means算法的效果可能不理想。

因此,在应用K-means算法时,需要根据具体问题和数据的特点来选择合适的K值和初始聚类中心,以及对数据进行预处理和后处理来改善聚类结果。

KMeans聚类算法

KMeans是如何工作的?

作为聚类算法的典型代表,KMeans可以说是最简单的聚类算法没有之一,那它是怎么完成聚类的呢?

在KMeans算法中,簇的个数K是一个超参数,需要我们人为输入来确定。KMeans的核心任务就是根据我们设定好 的K,找出K个最优的质心,并将离这些质心最近的数据分别分配到这些质心代表的簇中去。具体过程可以总结如下:

那什么情况下,质心的位置会不再变化呢?当我们找到一个质心,在每次迭代中被分配到这个质心上的样本都是一 致的,即每次新生成的簇都是一致的,所有的样本点都不会再从一个簇转移到另一个簇,质心就不会变化了。 这个过程在可以由下图来显示,我们规定,将数据分为4簇(K=4),其中白色X代表质心的位置: 

在数据集下多次迭代(iteration),模型就会收敛。第六次迭代之后,基本上质心的位置就不再改变了,生成的簇也 变得稳定。此时我们的聚类就完成了,我们可以明显看出,KMeans按照数据的分布,将数据聚集成了我们规定的 4类,接下来我们就可以按照我们的业务需求或者算法需求,对这四类数据进行不同的处理。

簇内误差平方和的定义和解惑

聚类算法聚出的类有什么含义呢?这些类有什么样的性质?我们认为,被分在同一个簇中的数据是有相似性的,而不同簇中的数据是不同的,当聚类完毕之后,我们就要分别去研究每个簇中的样本都有什么样的性质,从而根据业务需求制定不同的商业或者科技策略。我们追求聚类算法“簇内差异小,簇外差异大”。而这个“差异“,由样本点到其所在簇的质心的距离来衡量。 对于一个簇来说,所有样本点到质心的距离之和越小,我们就认为这个簇中的样本越相似,簇内差异就越小。而距 离的衡量方法有多种,令表示簇中的一个样本点, 表示该簇中的质心,n表示每个样本点中的特征数目,i表示组 成点 的每个特征,则该样本点到质心的距离可以由以下距离来度量:

而在KMeans中,我们在一个固定的簇数K下,最小化总体平方和来求解最佳质心,并基于质心的存在去进行聚类。整体距离平方和的最小值其实可以使用梯度下降来求解。簇内平方和整体平方和是KMeans的损失函数。 

scikit-learn中的KMeans

API Reference — scikit-learn 1.4.0 documentation

https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#sklearn.cluster.KMeans

重要参数 - n_clusters

n_clusters是KMeans中的k,表示着我们告诉模型我们要分几类。这是KMeans当中唯一一个必填的参数,默认为8 类,但通常我们的聚类结果会是一个小于8的结果。通常,在开始聚类之前,我们并不知道n_clusters究竟是多少, 因此我们要对它进行探索。 

首先,我们来自己创建一个数据集。这样的数据集是我们自己创建,所以是有标签的。

from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=1)
fig, ax1 = plt.subplots(1)
ax1.scatter(X[:, 0], X[:, 1]
           ,marker='o'
           ,s=8
           )
plt.show()
color = ["red","pink","orange","gray"]
fig, ax1 = plt.subplots(1)
for i in range(4):
    ax1.scatter(X[y==i, 0], X[y==i, 1]
           ,marker='o'
           ,s=8
           ,c=color[i]
           )
plt.show()

 

基于这个分布,我们来使用Kmeans进行聚类。首先,我们要猜测一下,这个数据中有几簇?

from sklearn.cluster import KMeans
n_clusters = 3
cluster = KMeans(n_clusters=n_clusters, random_state=0, n_init='auto').fit(X)
y_pred = cluster.labels_
y_pred[0:10]

pre = cluster.fit_predict(X)
(pre == y_pred)[0:10]

centroid = cluster.cluster_centers_
centroid

inertia = cluster.inertia_
inertia

color = ["red","pink","orange","gray"]
fig, ax1 = plt.subplots(1)
for i in range(n_clusters):
    ax1.scatter(X[y_pred==i, 0], X[y_pred==i, 1]
           ,marker='o'
           ,s=8
           ,c=color[i]
           )
ax1.scatter(centroid[:,0],centroid[:,1]
           ,marker="x"
           ,s=15
           ,c="black")
plt.show()

n_clusters = 4
cluster_ = KMeans(n_clusters=n_clusters, random_state=0, n_init='auto').fit(X)
y_pred_ = cluster_.labels_
y_pred_[0:10]

centroid_ = cluster_.cluster_centers_
centroid_

inertia_ = cluster_.inertia_
inertia_

color = ["red","pink","orange","gray"]
fig, ax1 = plt.subplots(1)
for i in range(n_clusters):
    ax1.scatter(X[y_pred_==i, 0], X[y_pred_==i, 1]
           ,marker='o'
           ,s=8
           ,c=color[i]
           )
ax1.scatter(centroid_[:,0],centroid_[:,1]
           ,marker="x"
           ,s=15
           ,c="black")
plt.show()

 聚类算法的模型评估指标

KMeans的目标是确保“簇内差异小,簇外差异大”,我们就可以通过衡量簇内差异来衡量聚类的效 果。我们刚才说过,Inertia是用距离来衡量簇内差异的指标,因此,我们是否可以使用Inertia来作为聚类的衡量指 标呢?Inertia越小模型越好嘛。

可以,但是这个指标的缺点和极限太大。

首先,它不是有界的。我们只知道,Inertia是越小越好,是0最好,但我们不知道,一个较小的Inertia究竟有没有达到模型的极限,能否继续提高。

第二,它的计算太容易受到特征数目的影响,数据维度很大的时候,Inertia的计算量会陷入维度诅咒之中,计算量会爆炸,不适合用来一次次评估模型。

第三,Inertia对数据的分布有假设,它假设数据满足凸分布(即数据在二维平面图像上看起来是一个凸函数的样 子),并且它假设数据是各向同性的(isotropic),即是说数据的属性在不同方向上代表着相同的含义。但是现实中的数据往往不是这样。所以使用Inertia作为评估指标,会让聚类算法在一些细长簇,环形簇,或者不规则形状的流形时表现不佳:

那我们可以使用什么指标呢?来使用轮廓系数。

在99%的情况下,我们是对没有真实标签的数据进行探索,也就是对不知道真正答案的数据进行聚类。这样的聚类,是完全依赖于评价簇内的稠密程度(簇内差异小)和簇间的离散程度(簇外差异大)来评估聚类的效果。其中轮廓系数是最常用的聚类算法的评价指标。

它是对每个样本来定义的,它能够同时衡量:

1)样本与其自身所在的簇中的其他样本的相似度a,等于样本与同一簇中所有其他点之间的平均距离

2)样本与其他簇中的样本的相似度b,等于样本与下一个最近的簇中得所有点之间的平均距离 根据聚类的要求”簇内差异小,簇外差异大“,我们希望b永远大于a,并且大得越多越好。 单个样本的轮廓系数计算为:

这个公式可以被解析为: 

很容易理解轮廓系数范围是(-1,1),其中值越接近1表示样本与自己所在的簇中的样本很相似,并且与其他簇中的样本不相似,当样本点与簇外的样本更相似的时候,轮廓系数就为负。当轮廓系数为0时,则代表两个簇中的样本相似度一致,两个簇本应该是一个簇。 如果一个簇中的大多数样本具有比较高的轮廓系数,则簇会有较高的总轮廓系数,则整个数据集的平均轮廓系数越高,则聚类是合适的。如果许多样本点具有低轮廓系数甚至负值,则聚类是不合适的,聚类的超参数K可能设定得太大或者太小。 在sklearn中,我们使用模块metrics中的类silhouette_score来计算轮廓系数,它返回的是一个数据集中,所有样本的轮廓系数的均值。但我们还有同在metrics模块中的silhouette_samples它的参数与轮廓系数一致,但返回的是数据集中每个样本自己的轮廓系数。 我们来看看轮廓系数在我们自建的数据集上表现如何: 

from sklearn.metrics import silhouette_score
from sklearn.metrics import silhouette_samples
X[0:10]


y_pred[0:10]

silhouette_score(X,y_pred)

cluster_.labels_[0:10]

silhouette_score(X,cluster_.labels_)

silhouette_samples(X,y_pred)[0:10]

轮廓系数有很多优点,它在有限空间中取值,使得我们对模型的聚类效果有一个“参考”。并且,轮廓系数对数据的 分布没有假设,因此在很多数据集上都表现良好。但它在每个簇的分割比较清洗时表现最好。但轮廓系数也有缺陷,它在凸型的类上表现会虚高,比如基于密度进行的聚类,或通过DBSCAN获得的聚类结果,如果使用轮廓系数来衡量,则会表现出比真实聚类效果更高的分数。

基于轮廓系数来选择n_clusters

我们通常会绘制轮廓系数分布图和聚类后的数据分布图来选择我们的最佳n_clusters。

# 基于轮廓系数来选择n_clusters

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
n_clusters = 4
fig, (ax1, ax2) = plt.subplots(1, 2)
fig.set_size_inches(18, 7)
ax1.set_xlim([-0.1, 1])
ax1.set_ylim([0, X.shape[0] + (n_clusters + 1) * 10])

clusterer = KMeans(n_clusters=n_clusters, random_state=10, n_init='auto').fit(X)
cluster_labels = clusterer.labels_
silhouette_avg = silhouette_score(X, cluster_labels)
print("For n_clusters =", n_clusters,
      "The average silhouette_score is :", silhouette_avg)
sample_silhouette_values = silhouette_samples(X, cluster_labels)
y_lower = 10
for i in range(n_clusters):
    ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]
    ith_cluster_silhouette_values.sort()
    size_cluster_i = ith_cluster_silhouette_values.shape[0]
    y_upper = y_lower + size_cluster_i
    color = cm.nipy_spectral(float(i)/n_clusters)
    ax1.fill_betweenx(np.arange(y_lower, y_upper)
                     ,ith_cluster_silhouette_values
                     ,facecolor=color
                     ,alpha=0.7
                     )
    ax1.text(-0.05
             , y_lower + 0.5 * size_cluster_i
             , str(i))
    y_lower = y_upper + 10
    
ax1.set_title("The silhouette plot for the various clusters.")
ax1.set_xlabel("The silhouette coefficient values")
ax1.set_ylabel("Cluster label")
ax1.axvline(x=silhouette_avg, color="red", linestyle="--")
ax1.set_yticks([])
ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])
colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
ax2.scatter(X[:, 0], X[:, 1]
           ,marker='o' #点的形状
           ,s=8 #点的大小
           ,c=colors
           )
centers = clusterer.cluster_centers_
ax2.scatter(centers[:, 0], centers[:, 1], marker='x',
            c="red", alpha=1, s=200)
ax2.set_title("The visualization of the clustered data.")
ax2.set_xlabel("Feature space for the 1st feature")
ax2.set_ylabel("Feature space for the 2nd feature")
plt.suptitle(("Silhouette analysis for KMeans clustering on sample data "
              "with n_clusters = %d" % n_clusters),
             fontsize=14, fontweight='bold')
plt.show()

将上述过程包装成一个循环,可以得到:

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
for n_clusters in [2,3,4,5,6,7]:    
    n_clusters = n_clusters
    fig, (ax1, ax2) = plt.subplots(1, 2)
    fig.set_size_inches(18, 7)
    ax1.set_xlim([-0.1, 1])
    ax1.set_ylim([0, X.shape[0] + (n_clusters + 1) * 10])
    clusterer = KMeans(n_clusters=n_clusters, random_state=10, n_init='auto').fit(X)
    cluster_labels = clusterer.labels_
    silhouette_avg = silhouette_score(X, cluster_labels)
    print("For n_clusters =", n_clusters,
          "The average silhouette_score is :", silhouette_avg)
    sample_silhouette_values = silhouette_samples(X, cluster_labels)
    y_lower = 10
    for i in range(n_clusters):
        ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]
        ith_cluster_silhouette_values.sort()
        size_cluster_i = ith_cluster_silhouette_values.shape[0]
        y_upper = y_lower + size_cluster_i
        color = cm.nipy_spectral(float(i)/n_clusters)
        ax1.fill_betweenx(np.arange(y_lower, y_upper)
                         ,ith_cluster_silhouette_values
                         ,facecolor=color
                         ,alpha=0.7
                         )
        ax1.text(-0.05
                 , y_lower + 0.5 * size_cluster_i
                 , str(i))
        y_lower = y_upper + 10
    ax1.set_title("The silhouette plot for the various clusters.")
    ax1.set_xlabel("The silhouette coefficient values")
    ax1.set_ylabel("Cluster label")
    ax1.axvline(x=silhouette_avg, color="red", linestyle="--")
    ax1.set_yticks([])
    ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])
    colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
    ax2.scatter(X[:, 0], X[:, 1]
               ,marker='o' #点的形状
               ,s=8 #点的大小
               ,c=colors
               )
    centers = clusterer.cluster_centers_
    ax2.scatter(centers[:, 0], centers[:, 1], marker='x',
                c="red", alpha=1, s=200)
    ax2.set_title("The visualization of the clustered data.")
    ax2.set_xlabel("Feature space for the 1st feature")
    ax2.set_ylabel("Feature space for the 2nd feature")
    plt.suptitle(("Silhouette analysis for KMeans clustering on sample data "
                  "with n_clusters = %d" % n_clusters),
                 fontsize=14, fontweight='bold')
    plt.show()

 

 

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

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

相关文章

随机图论基础

一,随机图、随机图空间 1,随机图 一个n个点的无向图,最多有sn(n-1)/2条边。 每条边都有一定的概率存在,有一定概率不存在,那么每个图都有一个出现概率。 2,随机图空间 一共有2^s种不同的图&#xff0c…

STM32外部中断原理及应用

对于嵌入式系统开发者而言,STM32系列微控制器是一个强大而灵活的选择,而外部中断作为其中一项重要的功能,为实时响应外部事件提供了关键支持。本文将带领初学者深入理解STM32外部中断的原理和应用,让你能够轻松地在你的项目中使用…

Jvm FullGC 如何排查?

使用场景 我们在使用系统时,有时请求和响应会变得特别慢,系统也变得很卡。 有可能是FullGC的问题,可以逐步地进行排查。 使用jps和top确定进程号pid jps可以列出正在运行的jvm进程,并显示jvm执行主类名称( main()函数所在的类…

[Vue3]父子组件相互传值数据同步

简介 vue3中使用setup语法糖,父子组件之间相互传递数据及数据同步问题 文章目录 简介父传子props传递值 使用v-bind绑定props需要计算toRefcomputed emit传递方法 使用v-on绑定 子传父expose v-model总结 父传子 props传递值 使用v-bind绑定 父组件通过props给子…

第三百零七回

文章目录 1. 概念介绍2. 使用方法3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何在输入框中提示错误"相关的内容,本章回中将介绍如何在输入框中处理光标.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在使用TextField组件作为…

【RT-DETR有效改进】UNetv2提出的一种SDI多层次特征融合模块(细节高效涨点)

👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 本问给大家带来的改进机制是UNetv2提出的一种多层次特征融合模块(SDI)其是一种用于替换Concat操作的模块,SDI模块的主要思想是通过整合编码器生成的层级特征图来增强图像中的语义信息和细节信息。包括皮肤…

远程连接服务器:Ping通但SSH连接失败的解决办法

写在前面:本博客仅作记录学习之用,部分图片来自网络,如需引用请注明出处,同时如有侵犯您的权益,请联系删除! 文章目录 前言常见问题影响SSH的因素本地影响因素防火墙设置网络配置文件 远程主机影响因素放行…

PyTorch 2.2 中文官方教程(二十)

移动设备 在 iOS 上进行图像分割 DeepLabV3 原文:pytorch.org/tutorials/beginner/deeplabv3_on_ios.html 译者:飞龙 协议:CC BY-NC-SA 4.0 作者:Jeff Tang 审阅者:Jeremiah Chung 介绍 语义图像分割是一种计算机视…

QCustomplot实现灰度曲线图

从 QCustomplot官网 https://www.qcustomplot.com/index.php/download 下载支持文件。首页有些demo可以进行参考学习。 新建一个Qt工程,将下载得到的qcustomplot.h和qcustomplot.cpp文件加入到当前工程。pro文件中加上 printsupport 在ui界面中,添加一…

Container 命令ctr、crictl 命令

1、 Containerd和Docker的架构区别 Docker vs. Containerd: 2、ctr & crictl的区别 ctr是containerd的一个客户端工具 crictl 是 CRI 兼容的容器运行时命令行接口,可以使用它来检查和调试 Kubernetes 节点上的容器运行时和应用程序 crictl 则直接对…

2024牛客寒假算法基础集训营1(视频讲解全部题目)

2024牛客寒假算法基础集训营1&#xff08;题目全解&#xff09; ABCDEFGHIJKLM 2024牛客寒假算法基础集训营1&#xff08;视频讲解全部题目&#xff09; A #include<bits/stdc.h> #define endl \n #define deb(x) cout << #x << " " << …

redis数据库设置对象的过期时间,到期后自动删除该条数据

redis数据库设置对象的过期时间,到期后自动删除该条数据&#xff01;过期时间的事情经常发生。比如大家领到了一些购物券。这张购物券有一个过期时间。必须在某节点之前&#xff08;某年某月末日&#xff09;之前&#xff0c;使用掉&#xff0c;否则该券就会过期&#xff0c;无…

ES高可用架构涉及常用功能整理

ES高可用架构涉及常用功能整理 1. es的高可用系统架构和相关组件2. es的核心参数2.1 常规配置2.2 特殊优化配置2.2.1 数据分片按ip打散2.2.2 数据分片机架感知2.2.3 强制要求数据分片机架感知2.2.4 写入线程池优化2.2.5 分片balance优化2.2.6 限流控制器优化 3. es常用命令3.1 …

超低价搭建cyberpanel+LiteSpeed企业版web服务器

注意&#xff0c;这里的企业版使用的是官方提供的免费密钥&#xff0c;在密钥激活后有一个月的有效时间&#xff0c;到期后官方会自动续期你的密钥 教学用配置&#xff1a; image1097698 126 KB 优惠链接&#xff1a;雨云 - 新一代云服务提供商 3 这是LiteSpeed&#xff08;以…

vue3 源码解析(5)— patch 函数源码的实现

什么是 patch 在 vue 中 patch 函数的作用是在渲染的过程中&#xff0c;比较新旧节点的变化&#xff0c;通过打补丁的形式&#xff0c;进行新增、删除、移动或替换操作&#xff0c;此过程避免了大量的 dom 操作&#xff0c;提升了运行的性能。 patch 执行流程 patch 函数整体…

0-MQTT基础使用教程【学习】

文件路径 MQTT基础使用教程1. MQTT1.1 MQTT简介1.1.1 什么是MQTT1.1.2 设计原则1.1.3 应用领域1.2 MQTT协议相关概念1.2.1 MQTT协议实现方式1.2.2 MQTT协议中的方法1.3 消息服务质量QoS1.3.1 消息服务质量QoS三个等级1.3.2 发布与订阅QoS1.4 Topic通配符匹配规则2. EMQX2.1 EMQ…

100183. 最大好子数组和

题目&#xff1a; 给你一个长度为 n 的数组 nums 和一个 正 整数 k 。 如果 nums 的一个子数组中&#xff0c;第一个元素和最后一个元素 差的绝对值恰好 为 k &#xff0c;我们称这个子数组为 好 的。换句话说&#xff0c;如果子数组 nums[i..j] 满足 |nums[i] - nums[j]| k…

Python基于时间序列分析的大气污染预测的设计与实现,附源码

1 简介 Python基于时间序列分析的大气污染预测的设计与实现 摘要&#xff1a;随着当今社会工业的发展&#xff0c;世界各地的空气质量都下降的非常明显&#xff0c;大气的污染对人们的身体健康会产生极大的危害。所以从20世纪初我国就十分关注空气质量的治理问题&#xff0c;…

【Java】Redis入门

1. Redis入门 1.1 Redis简介 Redis是一个基于内存的key-value结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件。 官网&#xff1a;https://redis.io 中文网&#xff1a;https://www.redis.net.cn/ key-value结构存储&#xff1a; 主要特点&#xff1a; 基于内…

【Android】使用Termux终端的SSH服务与电脑传输文件

在Android手机上有一个Termux APP&#xff0c;可运行类似 Linux 终端的模拟器&#xff0c;记得之前有讲过用电脑远程控制手机终端命令&#xff0c;那现在&#xff0c;怎样实现电脑与手机直接传输文件呢&#xff0c;且看这篇文章。 文章目录 Termux安装功能ssh服务从远程下载从本…