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

什么是无监督学习?

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

什么是聚类算法?

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

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

  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()

 

 

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

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

相关文章

重写Sylar基于协程的服务器(6、HOOK模块的设计)

重写Sylar基于协程的服务器(6、HOOK模块的设计) 重写Sylar基于协程的服务器系列: 重写Sylar基于协程的服务器(0、搭建开发环境以及项目框架 || 下载编译简化版Sylar) 重写Sylar基于协程的服务器(1、日志模…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之MenuItemGroup组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之MenuItemGroup组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、MenuItemGroup组件 该组件用来展示菜单MenuItem的分组。 子组件 无 接…

项目中使用sonar扫码代码

1.在maven的settings.xml配置 org.sonarsource.scanner.maven <profiles> <profile><id>sonar</id><activation><activeByDefault>true</activeByDefault></activation><properties><!-- Optional URL to server. D…

AI应用开发-git开源项目的一些问题及镜像解决办法

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享&#xff0c;包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…

okhttp 的 拦截器

拦截器有很多作用&#xff0c;实现就是责任链模式&#xff0c;细节&#xff0c;等我有时间补上。 后面有时间更新一下。 OkHttp最核心的工作是在 getResponseWithInterceptorChain() 中进行&#xff0c;在进入这个方法分析之前&#xff0c;我们先来了 解什么是责任链模式&…

【Linux】打包压缩跨系统/网络传输文件常用指令完结

Hello everybody!在今天的文章中我会把剩下的3-4个常用指令讲完&#xff0c;然后开始权限的讲解。那废话不多说&#xff0c;咱们直接进入正题&#xff01; 1.zip/unzip&tar命令 1.zip/unzip 在windows系统中&#xff0c;经常见到带有zip后缀的文件。那个东西就是压缩包。…

由于误删了node依赖,导致这后面的一系列操作

文章目录 1. 事发原因&#xff1a;Delete select files2. Delete select files引起的cross-env报错3. cross-env是node_modules的依赖工具4. 那么Delete selected files到底是什么操作5. 重装node_modules依赖包&#xff0c;也报错6. 报错&#xff1a;cb() never called!7. 算了…

JS第一天、数据类型检测、内存释放

复习&#xff1a; 以下类型都是 object console.log(typeof new Object); console.log(typeof new Array()); console.log(typeof new Date()); console.log(typeof new RegExp()); console.log(typeof new String()); console.log(typeof new Number()); console.log(typeof…

内裤洗衣机到底值不值得买?四款好用的内衣裤洗衣机推荐

随着内衣洗衣机的流行&#xff0c;很多小伙伴在纠结该不该入手一款内衣洗衣机&#xff0c;专门来洗一些贴身衣物&#xff0c;答案是非常有必要的&#xff0c;因为我们现在市面上的大型洗衣机只能做清洁&#xff0c;无法对我们的贴身衣物进行一个高强度的清洁&#xff0c;而小小…

Zoho Projects与Jira:中国市场的理想替代品之争?

在软件开发生命周期中&#xff0c;项目管理一直是一个非常重要的环节。为了更好地协作、追踪项目的进程和管理任务&#xff0c;许多公司选择了Jira这款著名的项目管理工具&#xff0c;它是个非常强大的工具&#xff0c;但是作为一款纯国外产品&#xff0c;他可能不适合中国市场…

CCReportAdv的一个配置技巧

关于CCReportAdv CCReportAdv是我们推出的基于经典WinCC/TIA WinCC Prof.的一款报表控件。它支持导入Excel模板&#xff0c;可以灵活生成美观的数据报表。 配置示例 CCReportAdv功能非常强大。通过简单的配置就可以生成客户需要的报表。以下面这款报表为例&#xff0c;参见下面…

STM32F407 CAN参数配置 250Kbps

本篇CAN参数适用 芯片型号&#xff1a;STM32F407xx系统时钟&#xff1a;168MHz&#xff0c;CAN挂载总线APB1为42M波 特 率 &#xff1a;250Kpbs引脚使用&#xff1a;TX_PB9&#xff0c;RX_PB8&#xff1b;修改为PA11PA12后&#xff0c;参数不变。 步骤一、打勾开启CAN&#xf…

20240131在ubuntu20.04.6下使用whisper不同模式的比对

20240131在ubuntu20.04.6下使用whisper不同模式的比对 2024/1/31 16:07 首先你要有一张NVIDIA的显卡&#xff0c;比如我用的PDD拼多多的二手GTX1080显卡。【并且极其可能是矿卡&#xff01;】 2、请正确安装好NVIDIA最新的驱动程序和CUDA。可选安装&#xff01; 3、配置whisper…

CTFshow 5——23

借鉴博客 misc5 下载完后&#xff0c;用winhex打开 在最后就可以找到flag misc6 和misc5一样 &#xff08;推测&#xff1a;可能是jpg这种看得见的图片&#xff0c;用winhex&#xff09; misc7 misc8 前置工具安装 这里可以看看见两个png 然后我们在我们的文件夹里面有个…

Oracle12c之修改连接数后导致的故障处理

Oracle12c之修改连接数后导致的故障处理 文章目录 Oracle12c之修改连接数后导致的故障处理1. 故障原因2. 故障信息3. 解决方法1. 首先登陆到数据库&#xff0c;创建临时pfile2. 手动修改创建的pfile.bac3. 以创建的临时文档启动数据库实例4.按照临时pfile中的内容重新创建pfile…

解决浏览器端 globalThis is not defined 报错

解决浏览器端 globalThis is not defined 报错 前言解决办法&#xff1a; 前言 在使用低版本火狐浏览器出现报错globalThis is not defined 解决办法&#xff1a; 在vue的index.html 中添加 this.globalThis || (this.globalThis this) <head><script>this.g…

C语言搭配EasyX实现贪吃蛇小游戏

封面展示 内部展示 完整代码 #define _CRT_SECURE_NO_WARNINGS #include<easyx.h> #include<stdio.h> #include<mmsystem.h> #pragma comment (lib,"winmm.lib") #define width 40//宽有40个格子 #define height 30//长有40个格子 #define size 2…

C++学习Day01之参数的传递方式

目录 一、程序及输出1.1 值传递1.2 地址传递1.3 引用传递1.5 引用注意事项1.5.1 引用必须引一块合法内存空间1.5.2 不要返回局部变量的引用1.5.3 当函数返回值是引用&#xff0c;那么函数的调用可以作为左值 二、分析与总结 一、程序及输出 1.1 值传递 #include<iostream&…

idea创建spring项目

一、环境 window10 IDEA 2022.2.3 maven-3.8.6 二、创建spring项目 1、新建Maven项目 File -> New -> Project 然后如下图选中Maven Archetype&#xff0c;在Archetype&#xff0c;选中maven-archetype-webapp&#xff0c;点击Create 2、配置maven 默认是使用IDEA内…