你还记得菜市场卖菜的吗?书店卖书的或者是平时去超市买东西时的物品,它们是不是都根据相似性摆放在一起了呢,饮料、啤酒、零食分布在各自区域,像这样各级事物的相似特点或特性组织在一起的方法,在机器学习里面即成为聚类,感觉是不是很简单呢,我们先以一个实例聚类来观察一下,有一个直观的感觉。
下面我们先来看一下数据,如下图所示
player :姓名
pos :表示球员打球的位置,后卫、防守等
pts :球员总共得分
g:是打球的场次
ast :助攻数量
tov :助攻失误数量
为了方便显示数据,我们暂且只使用这几列数据,其它数据也是可以使用的,维数太多了不方便展示,这里我们通过每位球员的平均得分和平均助攻数来作为特征衡量一个人进行聚类,意思是根据这个指标将人员进行自动分类,好比平时我们考试得分,班主任总是根据每个人的考试得分将本来就没几个人的班分为上等生、中等生、下等生,现在发现老师这么分等级是带有很大偏见的,毕竟社会考量一个人不仅仅是根据分数,而是一个人的总和能力。
平均得分(ppg) = 总得分(pts) / 打球场次(g)
平均助攻 = 总助攻(ast) / 助攻失误数量 (tov)
以下为手动实现聚类分析的代码,实现起来还是比较简单的,第一步是随机初始化n个质心,然后不断计算每个样本点到质心的距离,不断更新质心位置,如此循环往复,直到质心不再变化为止,即达到了我们的分类效果。
# 控球控制筛选 后卫人员
point_guards = nba[nba['pos']=='PG']
# 每场球赛得分
point_guards['ppg'] = point_guards['pts'] / point_guards['g']
# 平均助攻数量
point_guards = point_guards[point_guards['tov'] != 0 ]
point_guards['atr'] = point_guards['ast'] / point_guards['tov']
散点图展示如下:
plt.scatter(point_guards['ppg'],point_guards['atr'],c='g')
plt.title('Point Guards')
plt.xlabel('Points per Game',fontsize=15)
plt.ylabel('Radio',fontsize=15)
plt.show()
打球平均得分与助攻平均数散点图如下:
# 随机初始化5个质心
num_clusters = 5
random_initial_points = np.random.choice(point_guards.index,size=num_clusters)
centroids = point_guards.loc[random_initial_points]
print centroids
# 红色显示质心
plt.scatter(point_guards['ppg'],point_guards['atr'],c='y')
plt.scatter(centroids['ppg'],centroids['atr'],c='red')
plt.title('Centroids')
plt.xlabel('Points per Game',fontsize=15)
plt.ylabel('Radio',fontsize=15)
plt.show()
# 计算两点之间的欧式距离
def calcuate_distance(centroid,player_values):
root_distance = 0
for x in range(0,len(centroid)):
difference = centroid[x] - player_values[x]
squared_difference = difference**2
root_distance+= squared_difference
euclid_distance = math.sqrt(root_distance)
return euclid_distance
# 循环更新每点到质心的距离,选取最近的质心
def assigin_to_cluster(row):
lowest_distance = -1
closest_cluster = -1
for cluster_id,centroid in centroids_dict.items():
df_row = [row['ppg'],row['atr']]
euclidean_distance = calcuate_distance(centroid,df_row)
if (lowest_distance == -1):
lowest_distance=euclidean_distance
closest_cluster=cluster_id
print closest_cluster
elif (euclidean_distance < lowest_distance):
lowest_distance = euclidean_distance
closet_cluster = cluster_id
return closest_cluster
point_guards['cluster'] = point_guards.apply(lambda row : assigin_to_cluster(row),axis=1)
# 显示聚类后的数据点
def visualize_clusters(df,num_clusters):
colors = ['b','g','r','c','m','y']
print num_clusters
for n in range(num_clusters):
clustered_df = df[df['cluster'] == n]
print colors[n-1]
plt.scatter(clustered_df['ppg'],clustered_df['atr'],c=colors[n-1])
plt.xlabel('Points per Game',fontsize=15)
plt.ylabel('Assist tur ratio',fontsize=15)
plt.show()
visualize_clusters(point_guards,5)
上面是手动生成聚类算法的代码,其实很多库已经帮我们写好了,如很流行的sklearn 、tensorflow ,在性能和稳定性上都比我们自己写的好,没必要自己造轮子,sklearn代码如下:
# 引入sklearn框架
from sklearn.cluster import KMeans
# 初始化kmeans模型
kmeans = KMeans(n_clusters=num_clusters)
# 输入数据训练
kmeans.fit(point_guards[['ppg','atr']])
# 更新数据的簇标签
point_guards['cluster']=kmeans.labels_
# 展示数据
visualize_clusters(point_guards,num_clusters)
是不是觉的使用框架简单了好多,框架使得我们的工作重心从写繁琐的算法代码转移到了模型调参、数据特征分析上面,可以让我们事半功倍,一马平川,但这也并不是不用去关心算法内部实现以及原理,知道了算法原理有助于我们更好的理解模型参数,我们才知道如何去调节参数,两者相辅相成,缺一不可。
数据需要标准化处理,否则各维度计算的欧式距离可能差异比较大
因为质心随机生成,生成结果不稳定,多次运行结果可能不一样
维数过多后欧式距离可能不准,需要衡量距离算法
易于理解,和knn类似都是思路简单,容上上手,运行速度快
k值是我们设计者自己设定的值,依赖于设计者的经验水平,不同的人经验不同给出来的值可能也不一样,那么主观随意性就比较大,如果是研究可以,但是在工程上这种主观是不好的,效率不高,还是那句话我们不能重复造轮子,最好站在巨人肩膀上,登高而呼。
每种距离的计算方式都有自己的限制,再具体使用中需要结合样本的特点和场景不同合理选择描述样本之间相似性的算法,在这里我们说一下常见的几种算法。
欧氏距离
上面公式是一个通用公式,当p=2时即欧式距离,欧氏距离是我们最常用的距离计算方式,也成为几何距离,表示两个点的距离差平方和,简单直观
曼哈顿距离
当p=1时表示这个距离,计算的是两个点之间的实地走的距离,欧式距离时两点之间的空间直线距离,不考虑其它影响
向量內积
向量的內积在很多场合都在使用,向量內积是在向量空间里面,公式如下:
內积的结果是一个标量,大小没有限制,上下没有界限因此不好表示两个向量的相关性,于是有人提出来使用余弦来表示相似性,它有大小限制容易表示相似性。
1.为什么要有向量内积?向量內积的意义?
2.方差-聚类关系?
用一句话总结一件事才说名懂了,大道至简是自然规律,用一句话来描述聚类即 选定一个对象相似规则,不断更新质心,直至稳定。
什么限制了我们的创造性?
你是否思考过是什么限制了我们人的创造性呢?本科、研究生、还有博士水平可以说逐渐增高,对知识的理解和运用能力也是处于高层次阶段,拥有了大量专业水平可还是没有创造力,究其原因再加上思考,发现创造性是和知识量的积累没有必然联系,但大量的知识积累是创造的基础。
对世界的认知限制了我们的创造性,如果大家不相信,请思考一个问题,π(pai) 是什么?
当你接收身边任何事物时,别人告诉你了或你从书本上面得来的,都欣然接收了,但是没有思考其根源,具有推本溯源的意识,当你背诵乘法口诀、加法口诀时是否有疑问?1+1 为什么等于2? 1 又是什么,如果这个问题你想不清楚,那么如何创造出来更多的数字,要知道人类社会1出现在现代文明当中也就几百年 几代人而已,所谓科学家即推本溯源 追求真理的人,所谓真理即他创造出来被人们所接受的、对社会有意义东西。
参考资料:
1.https://zhuanlan.zhihu.com/p/27518705
2.https://zhuanlan.zhihu.com/p/30221347
3.https://zhuanlan.zhihu.com/p/34330242
4.https://zhuanlan.zhihu.com/p/20432322
5.https://blog.csdn.net/jbfsdzpp/article/details/48497347
6.http://www.cnblogs.com/daniel-D/p/3244718.html
7.https://zhuanlan.zhihu.com/p/24546995
8.https://zhuanlan.zhihu.com/p/20912337
9.https://blog.csdn.net/liulingyuan6/article/details/53637812