以余弦相似度将学生分组
cluster students into groups with cosine similarity
我有一个针对学生的 DataFrame,每个学生都由 6 门不同课程的二进制向量表示。即如果学生已经注册了这门课程,则1会被放在相应的位置,否则就是0。
import pandas as pd
import numpy as np
df_student = pd.DataFrame({'Name':['tom', 'Howard', 'Monty', 'Sean', 'mat',
'john', 'peter', 'lina', 'rory', 'joe'],
'math':[1,0,0,1,0,1,1,1,1,1],
'physics':[1,0,0,1,0,0,1,0,1,0],
'chemistry':[0,1,1,1,0,1,0,1,1,1],
'biology':[1,0,0,1,0,1,1,1,0,1],
'history':[0,0,0,0,1,1,0,1,0,1],
'geography':[0,1,1,1,0,1,0,1,0,1]})
看起来像:
Name math physics chemistry biology history geography
0 tom 1 1 0 1 0 0
1 Howard 0 0 1 0 0 1
2 Monty 0 0 1 0 0 1
3 Sean 1 1 1 1 0 1
4 mat 0 0 0 0 1 0
5 john 1 0 1 1 1 1
6 peter 1 1 0 1 0 0
7 lina 1 0 1 1 1 1
8 rory 1 1 1 0 0 0
9 joe 1 0 1 1 1 1
我想通过应用一些具有余弦相似度而不是欧氏距离的聚类算法将学生分组
因此,学生将被分组,例如在 k 个集群中,当我们有 10 个学生时,预期输出如下所示:
cluster_0:{tom, peter}
cluster_1:{Howard, Monty}
cluster_2:{Sean}
cluster_3:{mat}
cluster_4:{john, lina, joe}
cluster_5:{rory}
我们可以根据 cosine_similarity
的结果创建一个 DataFrame;然后 mask
小于 1 的值(由于存在一些舍入误差,我们 select 一个非常接近 1 的数字)和 stack
其余值。然后堆叠系列的索引包含我们想要的集群。要获得它们,我们使用 groupby
+ agg(set)
+ drop_duplicates
。然后我们从集群中创建一个字典:
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
df_student = df_student.set_index('Name')
df = pd.DataFrame(cosine_similarity(df_student),
index=df_student.index, columns=df_student.index)
clusters= (df.mask(df<1-np.finfo(float).eps)
.stack()
.index.to_frame()
.groupby(level=0)['Name'].agg(set)
.drop_duplicates())
clusters = (clusters.set_axis([f'cluster_{i}' for i in range(len(clusters))])
.to_dict())
输出:
{'cluster_0': {'Howard', 'Monty'},
'cluster_1': {'Sean'},
'cluster_2': {'joe', 'john', 'lina'},
'cluster_3': {'mat'},
'cluster_4': {'peter', 'tom'},
'cluster_5': {'rory'}}
我有一个针对学生的 DataFrame,每个学生都由 6 门不同课程的二进制向量表示。即如果学生已经注册了这门课程,则1会被放在相应的位置,否则就是0。
import pandas as pd
import numpy as np
df_student = pd.DataFrame({'Name':['tom', 'Howard', 'Monty', 'Sean', 'mat',
'john', 'peter', 'lina', 'rory', 'joe'],
'math':[1,0,0,1,0,1,1,1,1,1],
'physics':[1,0,0,1,0,0,1,0,1,0],
'chemistry':[0,1,1,1,0,1,0,1,1,1],
'biology':[1,0,0,1,0,1,1,1,0,1],
'history':[0,0,0,0,1,1,0,1,0,1],
'geography':[0,1,1,1,0,1,0,1,0,1]})
看起来像:
Name math physics chemistry biology history geography
0 tom 1 1 0 1 0 0
1 Howard 0 0 1 0 0 1
2 Monty 0 0 1 0 0 1
3 Sean 1 1 1 1 0 1
4 mat 0 0 0 0 1 0
5 john 1 0 1 1 1 1
6 peter 1 1 0 1 0 0
7 lina 1 0 1 1 1 1
8 rory 1 1 1 0 0 0
9 joe 1 0 1 1 1 1
我想通过应用一些具有余弦相似度而不是欧氏距离的聚类算法将学生分组
因此,学生将被分组,例如在 k 个集群中,当我们有 10 个学生时,预期输出如下所示:
cluster_0:{tom, peter}
cluster_1:{Howard, Monty}
cluster_2:{Sean}
cluster_3:{mat}
cluster_4:{john, lina, joe}
cluster_5:{rory}
我们可以根据 cosine_similarity
的结果创建一个 DataFrame;然后 mask
小于 1 的值(由于存在一些舍入误差,我们 select 一个非常接近 1 的数字)和 stack
其余值。然后堆叠系列的索引包含我们想要的集群。要获得它们,我们使用 groupby
+ agg(set)
+ drop_duplicates
。然后我们从集群中创建一个字典:
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
df_student = df_student.set_index('Name')
df = pd.DataFrame(cosine_similarity(df_student),
index=df_student.index, columns=df_student.index)
clusters= (df.mask(df<1-np.finfo(float).eps)
.stack()
.index.to_frame()
.groupby(level=0)['Name'].agg(set)
.drop_duplicates())
clusters = (clusters.set_axis([f'cluster_{i}' for i in range(len(clusters))])
.to_dict())
输出:
{'cluster_0': {'Howard', 'Monty'},
'cluster_1': {'Sean'},
'cluster_2': {'joe', 'john', 'lina'},
'cluster_3': {'mat'},
'cluster_4': {'peter', 'tom'},
'cluster_5': {'rory'}}