В классе учитель попросил сделать домашнее задание, классификацию kmeans, кластеризацию и классификацию радужной оболочки, поэтому я сделал это домашнее задание. Очень просто, я установил его в три категории. Дело в том, что когда я выбираю начальный центр, я пробовал два метода: случайный выбор и выбор большого хода. Эффект случайного выбора начальной точки не так хорош, как увеличение. Этот большой трюк заключается в следующем: сначала случайным образом выберите точку как центр1, затем выберите точку, наиболее удаленную от этого центра1, как центр2, а затем выберите точку, наиболее удаленную от центра1 и центра2, как центр3.
При обновлении центроида в процессе обучения, вместо выбора онлайн-режима для обновления центроида за раз, я выбрал режим mini_batch, сначала отправил образцы mini_batch и назначил их соответствующим центрам, а затем обновить. Столько ерунды, лучше выложить код, код такой:
import numpy as np
import csv
import random
features = np.loadtxt('iris.csv',delimiter=',',usecols=(1,2,3,4)) #read features
z_min, z_max = features.min(axis=0), features.max(axis=0) #features normalized
features = (features - z_min)/(z_max - z_min)
csv_file = open('iris.csv') #transform string to num label
csv_reader_lines = csv.reader(csv_file)
classes_list = []
for i in csv_reader_lines:
classes_list.append(i[-1])
labels = []
for i in classes_list:
if i=='setosa':
labels.append(0)
elif i=='versicolor':
labels.append(1)
else:
labels.append(2)
labels = np.array(labels)
labels = labels.reshape((150,1)) # transformm list to numpy type
data_index = np.arange(features.shape[0])
np.random.shuffle(data_index)
train_input = features[ data_index[0:120] ]
train_label = labels[ data_index[0:120] ]
test_input = features[ data_index[120:150] ]
test_label = labels[ data_index[120:150] ]
train_length = 120
K = 3
center_1_pos = random.randint(0,train_length)
center1 = train_input[ center_1_pos ]
# center1 = train_input[0]
# center2 = train_input[1]
# center3 = train_input[2]
# print(center1)
# print(center2)
# print(center3)
biggest_distance = 0.0
center_2_pos = 0
for i in range(train_length):#选择center2
dist = np.sum(pow( (center1 - train_input[i]),2 ))
if dist > biggest_distance:
biggest_distance = dist
center_2_pos = i
center2 = train_input[center_2_pos]
biggest_distance = 0.0
center_3_pos = 0
for i in range(train_length):#选择center3
dist = np.sum(pow( (center1 - train_input[i]), 2 )) + np.sum(pow( (center2 - train_input[i]) , 2))
if dist > biggest_distance:
biggest_distance = dist
center_3_pos = i
center3 = train_input[center_3_pos]
mini_batch = 20
for epoch in range(10):#在整个数据集上训练10次
for i in range(6):
belong1 = []
belong2 = []
belong3 = []
for j in range(mini_batch):#mini_batch
temp_index = mini_batch * i + j
belong = 1
dist_1 = np.sum(pow( ( center1 - train_input[mini_batch*i+j] ),2 ))
temp_dist = dist_1
dist_2 = np.sum(pow((center2 - train_input[mini_batch * i + j]), 2))
dist_3 = np.sum(pow((center3 - train_input[mini_batch * i + j]), 2))
if(dist_2 < temp_dist):
temp_dist = dist_2
belong = 2
if(dist_3 < temp_dist):
belong = 3
if belong==1:
belong1.append( temp_index )
elif belong == 2:
belong2.append(temp_index)
else:
belong3.append(temp_index)
for k in belong1:
center1 = center1 + train_input[k]
center1 = center1 / (1 + len(belong1))
for k in belong2:
center2 = center2 + train_input[k]
center2 = center2 / (1 + len(belong2))
for k in belong3:
center3 = center3 + train_input[k]
center3 = center3 / (1 + len(belong3))
b_1=[]
b_2=[]
b_3=[]
for l in range(test_input.shape[0]):#在测试机上进行测试
belong = 1
dist_1 = np.sum(pow((center1 - test_input[l]), 2))
temp_dist = dist_1
dist_2 = np.sum(pow((center2 - test_input[ l ]), 2))
dist_3 = np.sum(pow((center3 - test_input[ l ]), 2))
if (dist_2 < temp_dist):
temp_dist = dist_2
belong = 2
if (dist_3 < temp_dist):
belong = 3
if belong == 1:
b_1.append(test_label[l][0])
elif belong == 2:
b_2.append(test_label[l][0])
else:
b_3.append(test_label[l][0])
print()
print('epoch : {} / 10' .format(epoch+1))
print('center1: ',b_1)
print('center2',b_2)
print('center3: ',b_3)
Ниже приведен результат запуска моей программы:
epoch : 1 / 10
center1: [2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1]
center2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
center3: [2, 2, 2, 2, 2]
epoch : 2 / 10
center1: [2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1]
center2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
center3: [2, 2, 2, 2, 2]
epoch : 3 / 10
center1: [2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1]
center2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
center3: [2, 2, 2, 2, 2]
epoch : 4 / 10
center1: [2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1]
center2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
center3: [2, 2, 2, 2, 2]
epoch : 5 / 10
center1: [2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1]
center2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
center3: [2, 2, 2, 2, 2]
epoch : 6 / 10
center1: [2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1]
center2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
center3: [2, 2, 2, 2, 2]
epoch : 7 / 10
center1: [2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1]
center2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
center3: [2, 2, 2, 2, 2]
Результаты довольно хорошие на небольших наборах данных.
Примечание. Когда я читал данные радужной оболочки, я удалял имя атрибута первой строки, иначе было бы проблематично иметь дело с ним.
Эй, делать это небольшое домашнее задание тоже довольно интересно Я узнал о нормализации данных Nummpy, чтении CSV-файлов с помощью numpy и о том, как преобразовать типы символов в CSV-файлах в числовые метки.