
# Linear classifier

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets


POINT_N = 300
DIM_N = 2
CLUST_N = 2

data, target, Center = datasets.make_blobs(n_samples=POINT_N, centers=CLUST_N, cluster_std=0.9, n_features=DIM_N, center_box=(-10,10), random_state=0, return_centers=True)

slope = (Center[1][1]-Center[0][1])/(Center[1][0]-Center[0][0])
C0 = [(Center[0][0]+Center[1][0])/2, (Center[0][1]+Center[1][1])/2]


print("w1=", Center[1][0]-Center[0][0])
print("w2=", Center[1][1]-Center[0][1])
print("b=", -(Center[1][0]-Center[0][0])*C0[0] - (Center[1][1]-Center[0][1])*C0[1])

plt.figure(figsize=(6.5,9))
plt.scatter(data[:,0], data[:,1], c='black', marker='o')
plt.scatter(Center[:,0], Center[:,1], c='red', marker="*", s=100)
plt.axline((Center[0][0], Center[0][1]), slope=slope, color="blue", linestyle=(0, (5, 5)))
plt.axline((C0[0], C0[1]), slope=-1.0/slope, color="blue", linestyle=(0, (5, 5)))
plt.show()

class NNET0:
    def __init__(self):
        self.input_nodes = DIM_N
        self.output_nodes = 1
        self.weights_input_to_output = np.array([[Center[1][0]-Center[0][0]], [Center[1][1]-Center[0][1]]])
        self.output_bias = np.array([ -(Center[1][0]-Center[0][0])*C0[0] - (Center[1][1]-Center[0][1])*C0[1] ])
    def activation_function(self, x):
        return (1 if x>0 else 0)
    def run(self, features):
        input_output = np.dot(features, self.weights_input_to_output)
        return self.activation_function(input_output+self.output_bias)


network = NNET0()

pred = []
for i in range(POINT_N):
    pred.append(network.run(data[i]))

plt.figure(figsize=(6.5,9))
for i in range(POINT_N):
    if pred[i]:
        plt.scatter(data[i][0], data[i][1], c='blue', marker='o')
    else:
        plt.scatter(data[i][0], data[i][1], c='green', marker='o')
plt.scatter(Center[:,0], Center[:,1], c='red', marker="*", s=100)
plt.axline((C0[0], C0[1]), slope=-1.0/slope, color="black", linestyle=(0, (5, 5)))
plt.show()

print(1.0*sum(target==pred)/POINT_N)

print(network.weights_input_to_output, "\n", network.output_bias)
print('----------------------------------------------------------')

