#!/usr/bin/env python
# coding: utf-8

# In[58]:


#梯度下降算法
#学习率alpha,训练数据个数m
#先画散点图，判断预测曲线方程
#写出预测曲线方程，推导预测曲线方程的代价函数，推导预测曲线代价函数对各个变量的偏导数
#对逐个变量同步进行梯度下降
#通过代价函数随迭代次数的图像判断是否收敛，并且调节学习率
#以二次函数为例
#构造数据
import numpy as np
import matplotlib.pyplot as plt
#从以下函数获得用于挖掘的数据数据，原函数3*x^2+7*x+4做调整
#x=10*(np.random.random((1,20))-0.5)
#y=3*x**2+7*x+4+4*(np.random.random((1,20))-0.5)
#据此获得用于机器学习的数据
x=np.array([[1.49,1.27,-0.22,3.42,-4.39,2.09,3.12,-0.22,-0.76,-2.94,-4.61,-1.33,2.73,0.22,-3.1,2.45,-2.11,-0.21,-0.76,-1.64]])
y=np.array([[19.21,17.74,3.83,62.38,32.77,30.94,56.91,3.59,1.44,8.17,33.85,1.61,45.24,6.29,12.89,38.71,3.51,2.37,-0.25,2.45]])
m=x.size
#绘制数据点散点图
plt.subplot(2,1,1)
plt.scatter(x,y)
#预测像一个二次函数，形式是y=theta1*x^2+theta2*x+theta3,推导出代价函数是J(theta1,theta2,theta3)=2/m∑(theta1*x(i)
#^2+theta2*x(i)+theta3)
#推导对每一个变量的偏导数
#初始化学习率alpha，迭代次数iteration，变量theta1，2，3
alpha=0.003
iteration=1000
theta1=0
theta2=0
theta3=0
J=np.random.random((1,iteration))
for k in range(iteration):
    J[0,k]=1/2/m*np.sum((theta1*x**2+theta2*x+theta3-y)**2)
    a1=theta1-alpha/m*np.sum(x**2*(theta1*x**2+theta2*x+theta3-y))
    a2=theta2-alpha/m*np.sum(x*theta1*(x**2+theta2*x+theta3-y))
    a3=theta2-alpha/m*np.sum(theta1*x**2+theta2*x+theta3-y)
    #同步更新
    theta1=a1
    theta2=a2
    theta3=a3  
t=np.arange(iteration)+1
t=t[np.newaxis,:]
#得到代价函数随迭代次数的图像，用于判断是否收敛
plt.subplot(2,1,2)
plt.scatter(t,J)
plt.show()
#输出待求拟合参数theta1,2,3
print(theta1,theta2,theta3)
#得到2.7x^2+4.5x+4.5(可能是对原函数进行调整的幅度过大),不过二次项已经接近了

