初学机器学习,作为一个入门的新手,且第一次写博客,因为时间比较多同时也为了理解地更加深刻,就把自己的想法写出来,将来如果需要用到的话,也方便找到,理解地可能不是很准确,望大家理解。
重点内容
对机器学习的理解,所谓机器学习,就是机器从数据中学习,机器从数据中学出规律,然后运用到新的数据中,在机器学习中,前者称为训练集,后者称为测试集。
学机器学习,我们第一个往往学的是线性回归(linear regression),在这里,我从吴恩达教授讲的例子说起,吴恩达讲的是一个房屋价格与面积的关系,已知一部分房屋的面积与其价格,让我们预测新的房子的价格。
我们的目的是要找到一条直线,是的这些点尽量要靠拢这条直线。那么要如何找到这条直线呢?
接下来,我们就要建立一个模型,我们设房屋面积为X,那么房屋的价格可以用下式来表示:
上面的关系式中,X是特征,h(x)是标签,在本例中特征可以是房屋面积,房屋的卧室数目,房屋所处的楼层,只要是能够影响或者决定价格的因素都可以算,而theta(抱歉,我找不到Mathtype编辑器在哪)是参数,可以称之为权重,也就是特征能够对标签的贡献是多大。
那么,问题又来了,我们该如何选择theta才能使得这个模型是相对准确的呢,在这里我们需要定义一个损失函数,也称为惩罚函数,损失函数衡量的是预测值与真实值之间的差异。损失函数定义如下:
之所以这样定义损失是因为用数学问题很好解决,你也可以定义成其他方式,比如差的绝对值函数。
从上式看出,损失函数是一个二次函数,也就是说他是一个凸函数,具有全局最优解,也是因为它具有凸函数的性质,它才可以用梯度下降算法来解决,事实上,无论具有多少特征,也改变不了损失函数具有全局最优解的本质,例如当具有两个特征时,是一个碗状曲面,在本例中,损失函数是一个二次函数,我画了一个二次函数:
损失函数就是上面图的左右上下平移。接下来,我们就要求解theta了,我们的目的是要到达最低点,也就是让损失函数最小,在这里我们就想到了梯度,梯度是方向向量,因为某一点的梯度代表的是损失函数下降最快的方向,所以我们用导数更新theta.
为什么是“减号”,我们来看损失函数,当某处的斜率是负值时,我们要增加theta,这样就会离目标更近,当斜率是正值时,我们要减小theta,因此是“减号”。注意,损失函数的横轴代表theta.
我写了一个代码,是用的python.
代码如下:
import matplotlib.pyplot as plt
import numpy as np
from numpy import *
# Load the diabetes dataset 加载数据集
diabetes = datasets.load_diabetes()
# Use only one feature 该数据共6维,取第三列
diabetes_X = diabetes.data[:, np.newaxis, 2]
# Split the data into training/testing sets
diabetes_X_train = diabetes_X[:-20] #训练集为除去后面的20个
##############
diabetes_X_train1=diabetes_X
##############
#diabetes_X_test = diabetes_X[-20:] #测试集为后20个
# Split the targets into training/testing sets
diabetes_y_train = diabetes.target[:-20] #同
############
diabetes_y_train1=diabetes.target
#plt.scatter(diabetes_X_train1, diabetes_y_train1, color='black')
############
#定义loss function
X=diabetes_X_train1
y=diabetes_y_train1
w=np.zeros((2,1))
m=len(X)
X0=np.ones((1,m), dtype='float64')
XX=vstack((X0,X.T))#垂直连接函数
#estimation=np.dot(w.T,XX)
#J=0.5*np.dot(estimation-y,(estimation-y).T)
J0=np.zeros((1000,1),dtype='float64')
#梯度下降
#迭代次数1000,学习率0.1
lamada=0.1
iritation=1000
for i in range(1000):
estimation=np.dot(w.T,XX)
w0=w[0]-0.1/m*np.sum(estimation-y)
w1=w[1]-0.1/m*np.dot((estimation-y),X)
w[0]=w0
w[1]=w1
J0[i]=0.5/m*np.dot(estimation-y,(estimation-y).T)
plt.scatter(diabetes_X_train1, diabetes_y_train1, color='black')
plt.scatter(X.T,np.dot(w.T,XX), color='green', linewidth=1)
#plt.scatter(diabetes_X_train1[-20:], diabetes_y_train1[-20:], color='black')
#plt.plot(X.T[-20:],np.dot(w.T,XX)[-20:], color='green', linewidth=1)
plt.show()
t=arange(1000)
plt.plot(t,J0,color='red',linewidth=3)
plt.xticks(())
plt.yticks(())
plt.show()
print("参数为:" ,w)
#总结一下,迭代过程中,估计值也会随着参数的迭代而改变,第二,通常会除以一个m,
#虽然我不知道为什么没有加m就会迭代不出来,反正我的是这样,为什么那条直线用plot画不出来
#而我要画scatter图,为什么,最终得到的参数是对的。
先写到这里,如有错误欢迎指正。