def main():

    # 2
    data = np.genfromtxt('girls_age_weight_height_2_8.csv', delimiter=',')
    lr = LinearRegression()

    ones = np.ones(len(data))
    x = np.array([ones, data[:,0], data[:,1]]).transpose()
    y = data[:,2]

    # 2.1

    age_mean = np.mean(x[:,1])
    age_std = np.std(x[:,1])

    weight_mean = np.mean(x[:,2])
    weight_std = np.std(x[:,2])

    print "Feature 'age' - Mean: %f, STD: %f" % (age_mean, age_std)
    print "Feature 'weight' - Mean: %f, STD: %f" % (weight_mean, weight_std)

    x_scaled = np.array(x)

    x_scaled[:,0] = ones
    x_scaled[:,1] = (x[:,1] - age_mean)/age_std
    x_scaled[:,2] = (x[:,2] - weight_mean)/weight_std
    
    m, n = x.shape

    # 2.3
    
    alphas = [0.005, 0.001, 0.05, 0.1, 0.5, 1.0]
    iterations_n = 50
    iterations = np.arange(iterations_n)
    risk = np.zeros(shape = (iterations_n, len(alphas))).T

    for alpha_i in range(0, len(alphas)):
        theta_sim = np.zeros(n)
        for iteration_n in iterations:
            theta_sim = lr.gradient_descent(x_scaled, y, theta_sim, alphas[alpha_i], iteration_n)
            prediction = np.dot(x_scaled, theta_sim)
            loss = prediction - y
            risk[alpha_i][iteration_n] = lr.calculate_cost(loss, m)

    for alpha_i in range(0, len(alphas)):
        plt.plot(iterations, risk[alpha_i], label='Alpha: %f' % alphas[alpha_i])

    theta = lr.gradient_descent(x_scaled,y,np.zeros(n), 1.0, iterations_n)
    prediction = np.dot(x_scaled, theta)


    point_to_guess = [1.0, (5.0-age_mean)/age_std, (20.0-weight_mean)/weight_std]
    guess = np.sum(np.dot(theta, point_to_guess))

    print "Betas: %s" % (theta)
    print "The 5 year girl weighting 20 is approximately %f m tall." % (guess)
    print "error %f" % lr.calculate_cost(prediction -y, m)

    # 2.4
    
    p = np.matrix(x)
    theta = lr.normal_equation(p, y)
    theta = np.ravel(theta)
    guess = np.sum(np.dot(theta, [1.0, 5.0, 20.0]))
    prediction = np.dot(x, theta.flatten())

    print "Betas: %s" % (theta)
    print "The 5 year girl weighting 20 is approximately %f m tall." % (guess)
    print "error %f" % lr.calculate_cost(prediction - y, m)

    plt.ylabel('Risk')
    plt.xlabel('# of Iterations')
    plt.legend()
    plt.show()
def main():

    # 1.1
    data = np.genfromtxt('girls_train.csv', delimiter=',')
    lr = LinearRegression()

    ones = np.ones(len(data))
    x = np.array([ones, data[:,0]]).transpose()
    y = data[:,1]

    plt.scatter(x[:,1], y)
    plt.ylabel('Height')
    plt.xlabel('Age')

    # 1.2
    
    m, n = x.shape
    learning_rate = 0.05
    number_of_iterations = 1500
    theta = np.zeros(n)
    theta = lr.gradient_descent(x, y, theta, learning_rate, number_of_iterations)

    # 1.3 
    prediction = np.dot(x, theta)
    plt.plot(x[:,1], prediction, label = "%fx + %f" % (theta[1], theta[0]))
    plt.legend()

    theta0_vals = np.linspace(-1.0, 1.0, 100)
    theta1_vals = np.linspace(-1.0, 1.0, 100)
     
    Z = np.zeros(shape=(theta0_vals.size, theta1_vals.size))
     
    for t1, element in enumerate(theta0_vals):
        for t2, element2 in enumerate(theta1_vals):
            thetaT = np.zeros(shape=(2, 1))
            thetaT[0][0] = element
            thetaT[1][0] = element2

            guess = np.dot(x, thetaT).flatten()
            loss = guess - y

            Z[t1, t2] = lr.calculate_cost(loss, m)
    
    X, Y = np.meshgrid(theta0_vals, theta1_vals)
    
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    surf = ax.plot_surface(X, Y, Z)

    # 1.4
    
    print "Model: %fx + %f" % (theta[1], theta[0])
    print "Mean square error for training: %f" % lr.calculate_cost(prediction-y, m)
    print "Predicted height for a 4.5 years old girl: %f" % (4.5*theta[1] + theta[0])

    test_data = np.genfromtxt('girls_test.csv', delimiter=',')
    test_x = np.array([np.ones(len(test_data)), test_data[:,0]]).transpose()
    test_y = test_data[:,1]
    test_prediction = np.dot(test_x, theta)
    test_error = lr.calculate_cost(test_prediction - test_y, len(test_data))
    
    print "Mean square error for testing: %f" % (test_error)


    plt.show()