Как мне реализовать среднее смещение, используя сетку центроидов? - PullRequest
2 голосов
/ 23 марта 2019

Это для класса, и я был бы очень признателен за вашу помощь! Я сделал некоторые изменения на основе полученного комментария, но теперь я получаю еще одну ошибку .. Мне нужно изменить существующую функцию, которая реализует алгоритм среднего сдвига, но вместо того, чтобы инициализировать все точки как первый набор центроидов, функция создает сетку центроидов с сеткой на основе радиуса. Мне также нужно удалить центроиды, которые не содержат точек данных. Моя проблема в том, что я не понимаю, как исправить ошибку, которую я получаю!

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-7-de18ffed728f> in <module>()
     49 centroids = initialize_centroids(x)
     50 
---> 51 new_centroids = update_centroids(x, centroids, r = 1)
     52 
     53 print(len(centroids))
<ipython-input-7-de18ffed728f> in update_centroids(data, centroids, r)
     26         #print(len(centroids))
     27         #print(range(len(centroids)))
---> 28         centroid = centroids[i]
     29         for data_point in data:
     30             if np.linalg.norm(data_point - centroid) < r:
IndexError: index 2 is out of bounds for axis 0 with size 2

Я попытался использовать диапазон входного набора данных в качестве границ для сетки с точками, разделенными радиусом.

from sklearn import datasets
import numpy as np
import matplotlib.pyplot as plt


def initialize_centroids(data, r = 1):
    '''Creates a grid of centroids with grid based on radius'''

    data = np.array(data)
    xi,yi = min(range(len(data))), max(range(len(data)))
    mx = np.arange(xi,yi,r)
    x,y = np.meshgrid(mx,mx)
    centroids=np.vstack([x.ravel(), y.ravel()])
    return centroids

#update centroids based on mean of points that fall within a specified radius of each centroid

def update_centroids(data, centroids, r = 1):

    new_centroids = []

    for i in centroids:
        in_radius = []
        centroid = centroids[i] #this is where the error occurs
        for data_point in data:
            if np.linalg.norm(data_point - centroid) < radius:
                in_radius.append(data_point) #this list is appended by adding the new centroid to it if the above conition is satisfied. 

        new_centroid = np.mean(in_radius, axis=0) 
        #maybe another way to do the next part
        new_centroids.append(tuple(new_centroid)) 

    unique_centroids = sorted(list(set(new_centroids))) #for element in in_radius, if element in set skip else set.append(element(in_rad)). append does not work with set. 

    new_centroids = {i:np.array(unique_centroids[i]) for i in range(len(unique_centroids))}

    return new_centroids

#test function on:
x, y = datasets.make_blobs(n_samples=300, n_features = 2, centers=[[0, 7], [0, -7], [5,7], [5, 0]])

centroids = initialize_centroids(x)

new_centroids = update_centroids(x, centroids, radius = 2)

print(len(centroids))
print()
print(len(new_centroids))

#code for plotting initially: 
plt.scatter(x[:,0], x[:,1], color = 'k')

for i in range(len(new_centroids)):
    plt.scatter(new_centroids[i][0], new_centroids[i][1], s=200, color = 'r', marker = "*")

#code for plotting updated centroids:
new_centroids = update_centroids(x, new_centroids, radius = 2)

plt.scatter(x[:,0], x[:,1], color = 'k')

for i in range(len(new_centroids)):
    plt.scatter(new_centroids[i][0], new_centroids[i][1], s=200, color = 'r', marker = "*")

#code for iterations:
def iterate_to_conv(data, max_iter=100):

    centroids = initialize_centroids(data)
    iter_count = 0

    while iter_count <= max_iter:
        new_centroids = update_centroids(data, centroids, radius = 2)
        centroids = new_centroids
        iter_count += 1


    return centroids


centroids = iterate_to_conv(x)

plt.scatter(x[:,0], x[:,1], color = 'k')

for i in range(len(centroids)):
    plt.scatter(centroids[i][0], centroids[i][1], s=200, color = 'r', marker = "*")

Функция должна возвращать количество конечных центроидов. Я не продвинулся достаточно далеко, чтобы понять, как вся реализация среднего смещения будет работать с этой функцией.

1 Ответ

1 голос
/ 23 марта 2019

Когда вы запускаете этот цикл: for i in centroids i, который повторяется через центроиды, это не число, это вектор, поэтому появляется ошибка.Например, первое значение i может быть равно [0 1 2 0 1 2 0 1 2].Так что брать индекс этого не имеет смысла.Ваш код говорит, что нужно взять centroid = centroid [n1 n2 nk].Чтобы это исправить, вам действительно нужно изменить способ инициализации функции центроида.Meshgrid также не будет создавать N-мерную сетку, поэтому ваша Mesh-сетка может работать для 2-х измерений, но не для N. Надеюсь, это поможет.

...