import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np

"""
Explanation: Exercício 2-2
Vamos considerar classificação de dados 2D
Classes linearmente separáveis
A fronteira de decisão resultante ao se aplicar a regressão linear ou logística a um problema de classificação é sempre uma função linear (reta, plano, hiperplano). Fronteiras "tortuosas" não são possíveis.<br>
Aqui vamos examinar a aplicação da regressão logística para a classificação de dados 2D, cuja fronteira de decisão é sabidamente linear.
End of explanation
"""


# draw n random points

N = 100
x1 = np.random.exponential(size=N)
x2 = np.random.standard_normal(N)
X = np.vstack(zip(np.ones(N),x1, x2))

p = plt.figure()
p1 = p.add_subplot(121)
p1.plot(X[:,1],X[:,2],'rx')

# um vetor de pesos qualquer, que definirá a fronteira de decisão
w = np.array((-1, 0.7, 2.1))


# baseado na fronteira, rotular os dados como positivo ou negativo.
y = []
p2 = p.add_subplot(122)
for i in range(N):
    if  X[i,:].dot(w) > 0:
        p2.plot(X[i,1],X[i,2],'bo')  # o (bolinhas) azuis (blue)
        y.append(1)
    else:
        p2.plot(X[i,1],X[i,2],'ro')  # o (bolinhas) vermelhas (red)
        y.append(0)
        
y = np.array(y)

x = np.arange(0, max(X[:,1]), 0.01)
fx = [(-w[0]-w[1]*p)/w[2] for p in x ]
p2.plot(x, fx, lw=2)
plt.show()

"""
Explanation: 1. Criar um dataset com pontos 2D, linearmente separáveis
End of explanation
"""


# Supomos que o arquivo funcoes.py já está criado
from funcoes import gradientDescent, computeCost


# chutar uns pesos iniciais e calcular o custo inicial
w = np.zeros(3)

initialCost = computeCost(X, y, w)
print 'Initial cost: ', initialCost


# Some gradient descent settings
iterations = 500
alpha = 0.01


# run gradient descent
w, J_history = gradientDescent(X, y, w, alpha, iterations)

finalCost = computeCost(X, y, w)
print 'Final cost: ', finalCost


# solução matricial 
#XT = np.transpose(X)
#MP = np.linalg.inv(XT.dot(X))
#w = TMP.dot(XT.dot(y))


# plot do resultado
print 'Weight w found by gradient descent: ', w


for i in range(N):
    if  y[i]>0 :
        plt.plot(X[i,1],X[i,2],'bo')  # o (bolinhas) azuis (blue)
    else:
        plt.plot(X[i,1],X[i,2],'ro')  # o (bolinhas) vermelhas (red)
        
x = np.arange(0, max(X[:,1]), 0.01)
fx = [(-w[0]-w[1]*p)/w[2] for p in x ]
plt.plot(x, fx, lw=2)
plt.show()

"""
Explanation: 2. Aplicar regressão linear
End of explanation
"""


from funcoes2 import sigmoid, gradientDescent2, computeCost2

# chutar uns pesos iniciais e calcular o custo inicial
w = np.zeros(3)
initialCost = computeCost2(X, y, w)
print 'Initial cost: ', initialCost


# Some gradient descent settings
iterations = 500
alpha = 0.01

# run gradient descent
w, J_history = gradientDescent2(X, y, w, alpha, iterations)

finalCost = computeCost2(X, y, w)
print 'Final cost: ', finalCost

print w

R = X.dot(w)

for i in range(N):
    if  y[i]>0 :
        plt.plot(X[i,1],X[i,2],'bo')  # o (bolinhas) azuis (blue)
    else:
        plt.plot(X[i,1],X[i,2],'ro')  # o (bolinhas) vermelhas (red)
        
x = np.arange(0, max(X[:,1]), 0.01)
fx = [(-w[0]-w[1]*p)/w[2] for p in x ]
plt.plot(x, fx, lw=2)
plt.show()


"""
Explanation: 3. Aplicar regressão logística
End of explanation
"""


