下面进入练习,我们有如下的数据集, 表示在一个坐标系中的所有点的坐标。我们希望通过聚类分析,将坐标系中的点分成几个不同的类别。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.spatial.distance import cdist
from scipy.cluster.hierarchy import linkage, fcluster, dendrogram
from sklearn.cluster import KMeans
from sklearn.cluster import DBSCAN
data = pd.read_csv('clustering_data.csv')
print(data.head())
print(data.shape)
print(data.dtypes)

可以看到,通过shape属性,得知一共有1545个样本点,每个样本点有横纵坐标。
dtypes属性用于输出一个pandas dataframe中每个列数据类型的序列。要注意和dtype()函数做区分,dtype()只能作用于单个元素,并返回int,float等数据类型,而不能作用于类似列表和字典等容器,因为容器中存放了多种数据类型(但是dtype函数可以作用于np.array,因为数组只有一种数据类型)。
要想获得数据结构的类型,需要type()函数,会返回列表、字典等类型。
astype()函数用于改变数组中所有元素的数据类型,只有在能使用dtype()函数的前提下,才能使用astype()来改变类型
sns.scatterplot('x', 'y', data=data)
plt.title('Datapoints for Clustering')
plt.show()

sample = data.sample(200)
sns.scatterplot('x', 'y', data = sample) # data = 不能省略
plt.show()

scipy.cluster.hierarchy.linkage(y, method='single', metric='euclidean', optimal_ordering=False)
因为在导入库的阶段我们使用了scipy.cluster.hierarchy,所以后面我们可以直接使用函数名进行调用。
对linkage函数的参数做出以下说明:
y: 可以是1维压缩向量(距离向量),也可以是二维观测向量(坐标矩阵,就是这里的data)

method参数:




返回值:
层次聚类会输出一个linkage矩阵Z,这个矩阵由四列组成,第一列和第二列分别是聚类簇的编号,在初始距离前每个初始值被从0到n-1进行标识,每生成一个聚类簇就在此基础上增加一对新的聚类簇;第三列表示前面两个聚类簇之间的距离;第四列表示新生成的聚类簇包含的元素的个数。
# build linkage from scipy module
Z = linkage(sample, metric='euclidean', method='single')
print(Z)

假设我们的y是个mn矩阵,表示m条记录,每条记录由n个特征,那么返回的结果Z是一个 (m-1)4 的矩阵:
我们使用 print(Z.shape), 得出的结果是(199,4)
层次分析图从上到下看,依次是枝和叶。
第一列和第二列代表类标签,包含叶子和枝子。
第三列代表叶叶(或叶枝,枝枝)之间的距离
第四列代表该层次类中含有的样本数(记录数)
X = linkage(y, method='single', metric='euclidean')
method是指计算类间距离的方法,比较常用的有3种:
(1)single:最近邻,把类与类间距离最近的作为类间距
(2)average:平均距离,类与类间所有pairs距离的平均
(3)complete:最远邻,把类与类间距离最远的作为类间距
plt.figure(figsize=(15,7))
dendrogram(Z, distance_sort='descending', no_labels=True)
plt.axhline(y=2, color='r', linestyle = '-')
plt.show()

distance_sort: str 或 bool,可选
对于每个节点 n,绘制 n 的两个后代链接的顺序(视觉上,从左到右)由该参数确定,该参数可以是以下任何值:
False:什么都没做。
'ascending' 或 True:首先绘制其直接后代之间距离最小的孩子。
'descending':首先绘制其直接后代之间距离最大的孩子。
注意 distance_sort 和 count_sort 不能同时为 True。
no_labels: 布尔型,可选
当为 True 时,在树状图的渲染中,叶节点旁边不会出现任何标签。
*注意:在dendrogram图中,如果我们把水平线向下移动,那么基于层次的聚类会输出更多的聚类簇,但是簇与簇之间的距离变小了
data['cluster'] = fcluster(Z, 4, criterion='maxclust')
plt.figure(figsize=(10, 7))
sns.scatterplot(x='x', y='y', hue='cluster', data = data, legend= False, palette= ["purple", "red", "green", "orange"])
plt.show()
注意,fcluster函数输出的是一个数组,数组中的每个数字表示相应位置的元素属于哪个类别(类别用数字表示)。参数中的4表示我们希望把原始数据分成4个类别。
这样我们原有的数据就分成了如下所示的4个类别:

使用vq也能输出这张图:
from scipy.cluster.vq import kmeans, vq
cluster_centers, distortion = kmeans(data_kmeans, 4)
data_kmeans['labels'], distortion_list = vq(data_kmeans, cluster_centers)
sns.scatterplot(x='x', y='y', hue='labels', data=data_kmeans)
plt.show()

Kmeans算法的目的是选择出簇的质心,使得各个聚类得补的inertia值最小。inertia是类内聚合度的一种度量方式,我们可以把inertia使用append函数加入到 distortion列表中,从而进行可视化,选出最优的类的个数。
下面使用第一种方法,即kmeans的fit函数进行操作:
distortions = [] # 扭曲
K = range(1, 10)
for k in K: # range函数中间用逗号!!!!
km = KMeans(n_clusters=k)
km.fit(data_kmeans)
distortions.append(km.inertia_) #km.inertia_是个啥???
plt.figure(figsize=(16,8))
sns.lineplot(x=K, y=distortions, marker='x') # plt没有lineplot函数!!!!而且x参数需要一个序列
plt.xlabel('k')
plt.ylabel('Distortions')
plt.title('The elbow curve')
plt.show()

第二种方法:使用kmeans函数
from scipy.cluster.vq import kmeans, vq
num_clusters = range(1, 10)
distortions = []
for i in num_clusters:
centroids, distortion = kmeans(data_kmeans, i)
distortions.append(distortion)
plt.figure(figsize=(16, 8))
sns.lineplot(x=num_clusters, y=distortions, marker='x')
plt.xlabel('k')
plt.ylabel('distortions')
plt.title('The elbow curve')
plt.show()

这一节会构造KMeans类的对象,并对KMeans构造函数的参数进行讲解:
kmeans = KMeans(n_clusters= 7, init="random", n_init=1, max_iter=12).fit(data_kmeans)
data_kmeans["cluster"] = kmeans.labels_ # labels_ 以np array的形式输出原始数据聚类后的标签值
print(kmeans.labels_)
print(kmeans.labels_.size)
plt.figure(figsize=(10, 7))
sns.scatterplot(x='x', y='y', hue='cluster', data = data_kmeans, legend= False)
plt.show()

*注意:1. 这样划分并不理想, 2. labels_属性会以数组的形式输出不同的样本点所属的类别,输出的size是1545,说明每个样本点都进行了分类
上面通过fit函数训练好了KMeans对象,现在用这个训练好的模型做一些预测:
to_predict = pd.DataFrame({'x': [0,1,2,3], 'y': [0,1,2,3]})
print(to_predict)
kmeans.predict(to_predict)



*注意:sklearn包中,几乎所有的模型的建模函数都是fit,预测函数都是predict
def getcentroids(df, k):
x_cent = np.random.uniform(df.iloc[:,0].min(), df.iloc[:,0].max(), k)
y_cent = np.random.uniform(df.iloc[:,1].min(), df.iloc[:,1].max(), k)
return pd.DataFrame({"x": x_cent, "y": y_cent})
def kmeans_clust(x,k):
fd = x.copy()
# step a
# Choose k random points from the dataset
centroids = getcentroids(x, k)
# step b
#finding the distance between centroids and all the data points
distances = cdist(x, centroids ,'euclidean')
#print(pd.DataFrame(distances))
#Centroid with the minimum Distance
points = np.array([np.argmin(i) for i in distances])
#print(pd.DataFrame(points))
fig, ax = plt.subplots(4, 3, figsize=(18, 10))
ax = ax.ravel()
fig.tight_layout(pad=4)
#Repeating the above steps for a defined number of iterations
#Step c
for iter in range(12):
centroids = []
for idx in range(k):
#Updating Centroids by taking mean of Cluster it belongs to
temp_cent = x[points==idx].mean(axis=0)
centroids.append(temp_cent)
centroids = np.vstack(centroids) #Updated Centroids
distances = cdist(x, centroids ,'euclidean')
points = np.array([np.argmin(i) for i in distances])
fd["clusters"] = points
cent = pd.DataFrame(centroids)
sns.scatterplot("x", "y", hue="clusters", ax=ax[iter], data=fd, legend= False)
sns.scatterplot(0, 1, ax=ax[iter], data = cent, legend=False)
ax[iter].set_title(f'Iteration {iter}')
return points
函数原型: numpy.random.uniform(low,high,size)
功能:从一个均匀分布[low,high)中随机采样,注意定义域是左闭右开,即包含low,不包含high.
参数介绍:
low: 采样下界,float类型,默认值为0;
high: 采样上界,float类型,默认值为1;
size: 输出样本数目,为int或元组(tuple)类型,例如,size=(m,n,k), 则输出mnk个样本,缺省时输出1个值。
返回值:ndarray类型,其形状和参数size中描述一致。


DBSCAN(eps=0.5, min_samples=5, metric='euclidean', algorithm='auto', leaf_size=30, p=None, n_jobs=1)
参数介绍:
cluster = DBSCAN(eps=0.5, min_samples=6).fit(data_dbs)
data_dbs["cluster"] = cluster.labels_
plt.figure(figsize=(10, 7))
sns.scatterplot(x='x', y='y', hue='cluster', data = data_dbs, legend= False)
plt.show()

基于密度的聚类有以下优点:
缺点:
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的
本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决
2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p
1.在Python3中,下列关于数学运算结果正确的是:(B)a=10b=3print(a//b)print(a%b)print(a/b)A.3,3,3.3333...B.3,1,3.3333...C.3.3333...,3.3333...,3D.3.3333...,1,3.3333...解析: 在Python中,//表示地板除(向下取整),%表示取余,/表示除(Python2向下取整返回3)2.如下程序Python2会打印多少个数:(D)k=1000whilek>1: print(k)k=k/2A.1000 B.10C.11D.9解析: 按照题意每次循环K/2,直到K值小于等
ValidPalindromeGivenastring,determineifitisapalindrome,consideringonlyalphanumericcharactersandignoringcases. [#125]Example:"Aman,aplan,acanal:Panama"isapalindrome."raceacar"isnotapalindrome.Haveyouconsiderthatthestringmightbeempty?Thisisagoodquestiontoaskduringaninterview.Forthepurposeofthisproblem
是否可以在PyYAML或Ruby的Psych引擎中禁用创建anchor和引用(并有效地显式列出冗余数据)?也许我在网上搜索时遗漏了一些东西,但在Psych中似乎没有太多可用的选项,而且我也无法确定PyYAML是否允许这样做.基本原理是我必须序列化一些数据并将其以可读的形式传递给一个不是真正的技术同事进行手动验证。有些数据是多余的,但我需要以最明确的方式列出它们以提高可读性(anchor和引用是提高效率的好概念,但不是人类可读性)。Ruby和Python是我选择的工具,但如果有其他一些相当简单的方法来“展开”YAML文档,它可能就可以了。 最佳答案