从头开始用Python实现K-means算法

我有一段Python代码实现了k-means算法。我很难理解这段代码在做什么。比如C = X[numpy.random.choice(X.shape[0], k, replace=False), :]这样的代码行对我来说非常 confusing。

有人能解释一下这段代码到底在做什么吗?谢谢

def k_means(data, k, num_of_features):    # 将数据转换为矩阵
    X = data.as_matrix()    # 从数据中随机选择k个点
    C =  X[numpy.random.choice(X.shape[0], k, replace=False), :]    # 移除最后一列
    C = [C[j][:-1] for j in range(len(C))]    # 转换为numpy数组
    C = numpy.asarray(C)    # 存储质心更新时的值
    C_old = numpy.zeros(C.shape)    # 创建一个数组,用于将每个点分配到簇
    clusters = numpy.zeros(len(X))    # 误差函数 - 新旧质心之间的距离
    error = dist(C, C_old, None)    # 循环将持续到误差变为零或尝试5次
    tries = 0
    while error != 0 and tries < 1:        # 将每个值分配到最近的簇
        for i in range(len(X)):            # 按距离获取最近的簇
            clusters[i] = dist1(X[i][:-1], C)        # 存储旧的质心值
        C_old = deepcopy(C)        # 通过取平均值找到新的质心
        for i in range(k):            # 获取与当前簇匹配的所有点
            points = [X[j][:-1] for j in range(len(X)) if clusters[j] == i]            # 如果没有点被分配到簇,则置于原点
            if not points:                C[i][:] = numpy.zeros(C[i].shape)            else:                # 获取所有点的平均值,并将质心置于该位置
                C[i] = numpy.mean(points, axis=0)        # 误差是质心旧位置与新位置之间的距离
        error = dist(C, C_old, None)        # 增加尝试次数
        tries += 1
    return sil_coefficient(X,clusters,k)

回答:

(扩展回答,将来会格式化)X 是作为矩阵的数据。使用 [] 符号,我们是从矩阵中获取切片或选择单个元素。你可能需要复习 numpy 数组索引。 https://docs.scipy.org/doc/numpy/reference/arrays.indexing.htmlnumpy.random.choice 从数据矩阵的第一个维度大小中随机选择 k 个元素,不替换。注意,在索引中使用 [] 语法,我们看到有两个条目。numpy.random.choice 和 “:”。”:” 表示我们沿该轴取所有元素。

因此,X[numpy.random.choice(X.shape[0], k, replace=False), :] 表示我们沿第一个轴选择一个元素,并取与该第一个索引共享的所有元素沿第二个轴。实际上,我们是在选择矩阵的一行随机行。

(注释很好地解释了这段代码,我建议你进一步了解 numpy 索引和列表解析)。

C[C[j][:-1] for j in range(len(c))] 部分中的 “C[” 使用列表解析来选择矩阵 C 的一部分。

C[j] 代表矩阵 C 的行。我们使用 [:-1] 来获取行中除最后一个元素之外的所有元素。我们对矩阵 C 中的每一行都这样做。这移除了矩阵的最后一列。

C = numpy.asarray(C)。这将矩阵转换为 numpy 数组,以便我们可以对其进行特殊的 numpy 操作。

C_old = numpy.zeros(C.shape)。这创建了一个零矩阵,以后会被填充,其大小与 C 相同。我们正在初始化这个数组以便以后填充。

clusters = numpy.zeros(len(x))。这创建了一个零向量,其维度与矩阵 X 的行数相同。这个向量稍后会被填充。我们正在初始化这个数组以便以后填充。

error = dist(C, C_old, None)。计算两个矩阵之间的距离。我相信这个函数是在你的脚本中的其他地方定义的。

tries = 0。将尝试计数器设置为 0。

while…在该条件为真时执行该代码块。

for i in [0…(X 行数 – 1)]:

clusters[i] = dist1(X[i][:-1], C); 将 X 的第 i 行最接近的簇放在 clusters 的第 i 个位置。

C_old = deepcopy(C) – 创建 C 的一个新的副本。不要只是移动指针。

对于每个 (0..簇的数量 – 1):

points = [X[j][:-1] for j in range(len(X)) if clusters[j] == i]。这是列表解析。创建一个列表,包含 X 的行,去掉最后一个条目,但仅当该行属于第 j 个簇时才包含该行。

if not points。如果没有点属于某个簇。

C[i][:] = numpy.zeros(C[i].shape)。创建一个零向量,以后会被填充,并使用这个向量作为簇矩阵 C 的第 i 行。

else:

C[i] = np.mean(points, axis=0)。将簇矩阵 C 的第 i 行赋值为簇中点的平均值。我们沿行求和(axis=0)。这是我们在更新我们的簇。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注