sklearn 分类数据聚类
sklearn categorical data clustering
我正在使用 sklearn 和凝聚聚类函数。我有一个混合数据,其中包括数字和标称数据列。我的标称列的值是 "Morning"、"Afternoon"、"Evening"、"Night"。如果我通过分配诸如 0、1、2、3 之类的整数值将名义数据转换为数字; "Night" 和 "Morning" 之间的欧几里得距离将计算为 3,但是,1 应该是 return 作为距离的值。
X = pd.read_csv("mydata.csv", sep=",", header=0, encoding="utf-8")
X = StandardScaler().fit_transform(X)
print("n_samples: %d, n_features: %d" % X.shape)
km = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='average')
km.fit(X)
print("k = %d, Silhouette Coefficient: %0.3f" % (x,
metrics.silhouette_score(X, km.labels_, sample_size=None)))
这是我的代码。
如何在 sklearn 中自定义距离函数或将名义数据转换为数值?
此问题在机器学习应用程序中很常见。您需要将一个类别定义为基本类别(哪个类别无关紧要),然后为每个其他类别定义指示变量(0 或 1)。换句话说,创建 3 个名为 "Morning"、"Afternoon" 和 "Evening" 的新变量,并将一个变量分配给每个观测值的类别。如果是夜间观察,将这些新变量中的每一个都保留为0。
我认为您有 3 个选项可以将分类特征转换为数字特征:
- 使用OneHotEncoder。您会将分类特征转换为四个新列,其中只有一个 1,另一个为 0。这里的问题是 "morning" 和 "afternoon" 之间的差异与 "morning" 相同和 "evening".
- 使用OrdinalEncoder。您将分类特征转换为一列。 "morning" 到 1,"afternoon" 到 2 等。"morning" 和 "afternoon" 之间的差异将小于 "morning" 和 "evening" 这很好,但 "morning" 和 "night" 之间的差异将是最大的,这可能不是您想要的。
- 使用我称之为 two_hot_encoder 的转换。类似于OneHotEncoder,一行只有两个1。 "morning" 和 "afternoon" 之间的差异与 "morning" 和 "night" 之间的差异相同,并且小于 "morning" 和 "morning" 之间的差异"evening"。我认为这是最好的解决方案。检查代码。
代码:
def two_hot(x):
return np.concatenate([
(x == "morning") | (x == "afternoon"),
(x == "afternoon") | (x == "evening"),
(x == "evening") | (x == "night"),
(x == "night") | (x == "morning"),
], axis=1).astype(int)
x = np.array([["morning", "afternoon", "evening", "night"]]).T
print(x)
x = two_hot(x)
print(x)
输出:
[['morning']
['afternoon']
['evening']
['night']]
[[1 0 0 1]
[1 1 0 0]
[0 1 1 0]
[0 0 1 1]]
然后我们可以测量距离:
from sklearn.metrics.pairwise import euclidean_distances
euclidean_distances(x)
输出:
array([[0. , 1.41421356, 2. , 1.41421356],
[1.41421356, 0. , 1.41421356, 2. ],
[2. , 1.41421356, 0. , 1.41421356],
[1.41421356, 2. , 1.41421356, 0. ]])
我正在使用 sklearn 和凝聚聚类函数。我有一个混合数据,其中包括数字和标称数据列。我的标称列的值是 "Morning"、"Afternoon"、"Evening"、"Night"。如果我通过分配诸如 0、1、2、3 之类的整数值将名义数据转换为数字; "Night" 和 "Morning" 之间的欧几里得距离将计算为 3,但是,1 应该是 return 作为距离的值。
X = pd.read_csv("mydata.csv", sep=",", header=0, encoding="utf-8")
X = StandardScaler().fit_transform(X)
print("n_samples: %d, n_features: %d" % X.shape)
km = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='average')
km.fit(X)
print("k = %d, Silhouette Coefficient: %0.3f" % (x,
metrics.silhouette_score(X, km.labels_, sample_size=None)))
这是我的代码。
如何在 sklearn 中自定义距离函数或将名义数据转换为数值?
此问题在机器学习应用程序中很常见。您需要将一个类别定义为基本类别(哪个类别无关紧要),然后为每个其他类别定义指示变量(0 或 1)。换句话说,创建 3 个名为 "Morning"、"Afternoon" 和 "Evening" 的新变量,并将一个变量分配给每个观测值的类别。如果是夜间观察,将这些新变量中的每一个都保留为0。
我认为您有 3 个选项可以将分类特征转换为数字特征:
- 使用OneHotEncoder。您会将分类特征转换为四个新列,其中只有一个 1,另一个为 0。这里的问题是 "morning" 和 "afternoon" 之间的差异与 "morning" 相同和 "evening".
- 使用OrdinalEncoder。您将分类特征转换为一列。 "morning" 到 1,"afternoon" 到 2 等。"morning" 和 "afternoon" 之间的差异将小于 "morning" 和 "evening" 这很好,但 "morning" 和 "night" 之间的差异将是最大的,这可能不是您想要的。
- 使用我称之为 two_hot_encoder 的转换。类似于OneHotEncoder,一行只有两个1。 "morning" 和 "afternoon" 之间的差异与 "morning" 和 "night" 之间的差异相同,并且小于 "morning" 和 "morning" 之间的差异"evening"。我认为这是最好的解决方案。检查代码。
代码:
def two_hot(x):
return np.concatenate([
(x == "morning") | (x == "afternoon"),
(x == "afternoon") | (x == "evening"),
(x == "evening") | (x == "night"),
(x == "night") | (x == "morning"),
], axis=1).astype(int)
x = np.array([["morning", "afternoon", "evening", "night"]]).T
print(x)
x = two_hot(x)
print(x)
输出:
[['morning']
['afternoon']
['evening']
['night']]
[[1 0 0 1]
[1 1 0 0]
[0 1 1 0]
[0 0 1 1]]
然后我们可以测量距离:
from sklearn.metrics.pairwise import euclidean_distances
euclidean_distances(x)
输出:
array([[0. , 1.41421356, 2. , 1.41421356],
[1.41421356, 0. , 1.41421356, 2. ],
[2. , 1.41421356, 0. , 1.41421356],
[1.41421356, 2. , 1.41421356, 0. ]])