I'm a beginner in Python but I have tried to implement K-means algorithm in python and it's working... but it's too slow... Instead of few seconds I can spend hours to finish it and I don't know why... something it's wrong... Could anyone of you give me some advice please?
Code:
import math
from random import randint
from copy import deepcopy
from chart import chart_centroids, save_image
centroid = dict(x=0, y=0, points_x=[], points_y=[])
list_centroids = []
x = []
y = []
k = 0
def distance(x1, y1, x2, y2):
x = (int(x1) - int(x2)) ** 2
y = (int(y1) - int(y2)) ** 2
sum = x + y
sqr = math.sqrt(sum)
return sqr
def generate_centroids(range_x, range_y):
list_centroids.clear()
k = 3
for i in range(0, k):
centroid["x"] = randint(1, range_x)
centroid["y"] = randint(1, range_y)
list_centroids.append(deepcopy(centroid))
def choose_points_for_centroids(x, y):
for i in range(len(list_centroids)):
list_centroids[i]["points_x"].clear()
list_centroids[i]["points_y"].clear()
distances = []
for j in range(len(x)):
for i in range(len(list_centroids)):
dist = distance(x[j], y[j], list_centroids[i]["x"], list_centroids[i]["y"])
distances.append(dist)
minim = min(float(s) for s in distances)
index = distances.index(minim)
list_centroids[index]["points_x"].append(x[j])
list_centroids[index]["points_y"].append(y[j])
distances.clear()
def move_centroids():
sum_x = 0
sum_y = 0
for cent in list_centroids:
for j in range(len(cent["points_x"])):
sum_x += cent["points_x"][j]
sum_y += cent["points_y"][j]
if len(cent["points_x"]) > 0 and len(cent["points_y"]) > 0:
avg_x = sum_x / len(cent["points_x"])
avg_y = sum_y / len(cent["points_y"])
cent["x"] = avg_x
cent["y"] = avg_y
def run():
generate_centroids(300, 300)
read_file("input.txt")
tmp_x = []
tmp_y = []
checkers = []
while_end = False
while True:
if not while_end:
choose_points_for_centroids(x, y)
move_centroids()
for cent in list_centroids:
tmp_x.append(cent["x"])
tmp_y.append(cent["y"])
choose_points_for_centroids(x, y)
move_centroids()
for i in range(len(list_centroids)):
if tmp_x[i] == list_centroids[i]["x"] and tmp_y[i] == list_centroids[i]["y"]:
checkers.append(True)
else:
checkers.append(False)
for checker in checkers:
if not checker:
tmp_x.clear()
tmp_y.clear()
break
else:
while_end = True
else:
break
for i in range(len(list_centroids)):
chart_centroids(list_centroids[i], i)
save_image()
def read_file(name):
lines = [line.rstrip('\n') for line in open('../generate_file/' + name)]
global x
global y
zone = []
for index in range(5):
x.append(int(lines[index].split()[0]))
y.append(int(lines[index].split()[1]))
zone.append(int(lines[index].split()[2]))
run()
The input file it's looks something like...
100 52 2
440 100 3
10 200 1
...
Note: The code works in both Python 2 and Python 3.