# Задание 2.  (из  темы  4.2, тест 2):
# С помощью нейронной сети на основе анализа набора характеристик, непонятно как влияющих на отнесение к классам,
# произвести классификацию транспортных средств по классам: Легковой автомобиль; Пассажирский транспорт;
# Грузовой транспорт.
# За основу взять следующие характеристики:
# 0) Большая снаряженная масса,
# 1) Большая мощность двигателя,
# 2) Большая пассажировместимость,
# 3) Большая грузоподъёмность.
import numpy as np


def nonlin(x, deriv=False):
    if deriv:
        return x * (1 - x)
    return 1 / (1 + np.exp(-x))

def normalize(X):
    return (X - X.mean()) / X.std()

X = np.array([[0.645, 2.88, 1.11, 10.4, 2.88, 9.895, 3.695, 2.17, 27.895],  # снаряженная масса
              [33, 152, 88, 260, 152, 122, 136, 116, 278],  # мощность двигателя
              [4, 14, 5, 3, 3, 30, 3, 5, 150],  # пассажировместимость
              [0.34, 1.5, 0.475, 6, 1.5, 6.2, 3, 0.6, 11]]).T  # грузоподъёмность

y = np.array([[1, 0, 1, 0, 0, 0, 0, 1, 0],  # Легковой или нет? (1 - да, 0 - нет)
              [0, 1, 0, 0, 0, 1, 0, 0, 1],  # Пассажирский или нет? (1 - да, 0 - нет)
              [0, 0, 0, 1, 1, 0, 1, 0, 0]]).T  # Грузовой или нет? (1 - да, 0 - нет)

for x in X:
    x = normalize(x)
for y_ in y:
    y_ = normalize(y_)

syn0 = 2 * np.random.random((4, 6)) - 1
syn1 = 2 * np.random.random((6, 3)) - 1

for j in range(60000):
    l0 = X
    l1 = nonlin(np.dot(l0, syn0))
    l2 = nonlin(np.dot(l1, syn1))
    l2_error = y - l2

    if (j % 10000) == 0:
        print('Error: ' + str(np.mean(np.abs(l2_error))))

    l2_delta = l2_error * nonlin(l2, deriv=True)
    l1_error = l2_delta.dot(syn1.T)
    l1_delta = l1_error * nonlin(l1, deriv=True)

    syn1 += l1.T.dot(l2_delta)
    syn0 += l0.T.dot(l1_delta)

print('Output: ')
print(l2)

# Теперь эксперимент для велосипеда
X = np.array([[0.02],  # снаряженная масса
              [0.3],  # мощность двигателя
              [1],  # пассажировместимость
              [0.1]]).T  # грузоподъёмность

for x in X:
    x = normalize(x)

l0 = X
l1 = nonlin(np.dot(l0, syn0))
l2 = nonlin(np.dot(l1, syn1))

print('Output for bicycle: ')
print(l2)