Ваше время l oop никогда не заканчивается. Вы никогда не изменяете sub1
или sub2
, поэтому l oop просто вращается и вращается, а sub1
всегда меньше sub2
.
Проблема, с которой вы сталкиваетесь, заключается в том, что на каждом итерации, пока l oop, вы работаете с новыми кластерами на основе среднего значения от старых кластеров, а затем проверяете, изменились ли они.
Вы правы, что вам нужно какое-то время l oop, вы можете использовать что-то вроде этого:
def clusterAnalysis(reflectance):
# Work out your odd/even clusters to start it off
# EDIT: I misread how this bit works - see the update.
# You don't want to use the size here:
# you want to use a list of numbers the size
# of reflectance [0, 1, 2, ..., n]
even_numbers = np.arange(reflectance.size) % 2 == 0
# Now we'll create an array to hold the cluster ids, that's the
# same shape as reflectance.
# By default it'll store ones. Then we'll change all the entries
# for even numbers to hold twos
clusters = np.ones(reflectance.shape)
# This uses what's called "logical indexing" - it'll change all the elements
# that equal "true" in even_numbers
clusters[even_numbers] = 2
# This will create a never-ending while loop, but we'll manually
# end it using 'break'
while True:
# Work out the new clusters, by working out the means of the two
# clusters and finding the closest to the reflectance numbers
# Clue: You can use logical indexing here like we did above
cluster_1_mean = ...
cluster_2_mean = ...
new_clusters = ...
# This is the really important bit - we've created the new array
# `new_clusters` above and we want to check if it's the same as
# the last one. If it is, we'll use `break` which tells python
# to stop doing the loop now.
if np.all(clusters == new_clusters):
break
# We'll only reach here if we haven't called 'break' - so we'll update with the new clusters and we can go again
clusters = new_clusters
# Once the while loop is finished, we should return the clusters array.
return clusters
РЕДАКТИРОВАТЬ: Я постараюсь дать вам кусочки головоломки для бит кластеризации.
Допустим, у меня есть два списка из 20 случайных чисел от 0 до 200, и я хочу получить среднее значение нечетных и четных значений:
x = np.random.randint(200, size=(20))
# Just like above, we'll get the id of each element in an array [0, 1, ..., 20]
x_ids = np.arange(x.size)
evens = x_ids % 2 == 0
# We'll get the mean of all the even `x`'s
mean_even = np.mean(x[evens])
# And we can do it the other way round for the odds
mean_odd = np.mean(x[np.logical_not(evens)])
Другое редактирование:
ОК, последний кусок головоломки:)
Итак, мы хотим найти, какой из x
ближе всего к mean_even
, а какой ближе к mean_odd
. Мы можем сделать что-то похожее на вашу первоначальную попытку:
diff_even = np.abs(x - mean_even)
diff_odd = np.abs(x - mean_odd)
# Start by creating a new clusters array, just like we did before,
# where all the ids are originally set to `1`.
new_clusters = np.ones(x.shape)
# Now get the numbers closest to `diff_even` and set their cluster to
# two.
# Because we're using less-than, it means that any that are equally
# close to both means will stay in cluster one. If we wanted it to
# work so they went to cluster 2 by default, we could use `<=`.
new_clusters[diff_even < diff_odd] = 2
Вам нужно будет изменить некоторые имена переменных, чтобы использовать логическое индексирование, чтобы получить средства из массива кластеров вместо массива четных, но это должно дать вам в основном все, что вам нужно.
Обратите внимание, что я сделал ошибку раньше, когда сделал mean_odd
. Я нарушил логическое индексирование, случайно превратив логический массив в числа, поэтому я обновил его для использования np.logical_not
. Я могу объяснить, как это работает более подробно, если это интересно.