1 What is Machine-learning?
- Tom Mitchell: 机器学习是指一个程序从经验E(计算机与自己进行上万次的对弈)中学习解决某项任务T(玩跳棋),进行某一项性能度量P(赢跳棋的概率),通过P测定在T上的表现因经验E而提高。
2 Machine learning algorithm:
2.1 Supervised learning:
定义:
给出一些数据集与正确的答案(‘right answers’ given/Regression/Classification)希望计算机进行预测,并得出“正确答案”。比如:房子的大小与对应的房价,然后让计算机可以拟合出一条线,得出更多正确的答案
Regression:
Classification:
练习题:
- 问题一:我有大量相同货物的库存,想要预测在下面三周会卖出多少件?(连续变量:Regression)
- 问题二:让计算机去测试一下用户的账户,确定每个账户是被攻击或被破坏了(分类变量:Classification)
2.2 Unsupervised learning:
定义:
给计算机一组数据,没有答案,让计算机帮我们看看这组数据当中有没有什么规律或者数据是否存在不同的蔟(下图为聚类:Google新闻将费别相同的新闻进行分类)
练习:
答案:2、3
3 线性回归算法:
3.1 损失函数
我们的目标就是要求得最小的代价函数数!
上面的几张图片展示出了代价函数与拟合线准确性的关系,当代价函数越小,也就是越接近中心,那么拟合线的准确性就会越高。
那么如何能够找到最小的代价函数呢?
我们应使得下面的hypothesis函数(下面简称h函数)与x所对应的实际值y越接近!
又因为h函数是由两个未知参数所控制的,那我们的目标就转变为找到最优的这两个未知参数,使得h函数能够和y非常的接近。
要实现这个,那就要使用梯度下降算法了!
3.2 梯度下降算法
Batch-gradient descent:
其中:=符号表示赋值而非等于(也就是说每次都会更新一个值)
首先解释求求偏导部分:
- 求偏导的目的基本上可以说取这个红点的切线,就是这样一条红色的直线,刚好与函数相切于这一点,让我们看看这条红色直线的斜率,就是这条刚好与函数曲线相切的这条直线,这条直线的斜率正好是这个三角形的高度除以这个水平长度,现在,这条线有一个正斜率,也就是说它有正导数,因此,我得到的新的θ_1,θ_1更新后等于θ_1减去一个正数乘以a,也就是说θ_1变小了,j也就会变小,进一步的向j的最小点逼近。
- 同样的,当我们所求的为负斜率,我们的θ_1就会变大,也会向j的最小点逼近(可以把这个偏导当作是一个自动的方向盘,它总是确保行驶的方向向j的最小点去逼近)
- 而alpha就是步长,也可以称作是学习速率,alpha过小会使得车开的很慢,alpha过大会使得车开的太快,可能会跨过那个最小点。
- 观察下图,在那个紫色的点初始化,如果我更新一步梯度下降,那么我可能会到达绿色的点,因为这个点的导数(斜率)是相当陡的。如果我再更新一步,你会发现我的导数,也是没那么陡的,到达下一个红色的点。随着我接近最低点,我的导数越来越接近零,所以,梯度下降一步后,新的导数会变小一点点。然后我想再梯度下降一步,在这个绿点,我自然会用一个稍微跟刚才在那个品红点时比,再小一点的一步,到了新的红色点,更接近全局最低点了,因此这点的导数会比在绿点时更小。所以,我再进行一步梯度下降时,我的导数项是更小的,θ_1更新的幅度就会更小。所以随着梯度下降法的运行,你移动的幅度会自动变得越来越小,直到最终移动幅度非常小,你会发现,已经收敛到局部极小值。
假设我们只有一个特征变量,那么此时我们的代价函数的偏导数是这样的:
可以写成这样:
3.3 多变量梯度下降:
从上面的公式当中我们可以看到,我们由n+1个参数,n个特征变量。通常为了简化,我们会设x0=1,这样我们就有了n+1个参数和n+1个变量了。
因此我们就可以做向量的乘法了。
3.4 梯度下降缩放:
当我们的特征值取值范围相差比较大的时候,比如我们有两个特征,一个是房子的大小,一个是房间数,这时我们会发现我们的这两个特征取值范围是比较大的,在计算代价函数的时候图像就会像下面那样,非常的高细,要走很多步才会到最优点。
通常我们可以采用缩放法:
或是:
3.5 确定迭代次数
因为梯度下降算法收敛所需要的迭代次数根据模型的不同而不同,我们无法预知,如果迭代次数太少就难以得到最优的解,如果过多就会造成过多的计算。通常可以通过绘图来计算。
3.6 多项式回归
有时,我们的一次项模型可能无法非常准确的拟合我们的数据,因此,我们可能会去采用其他多项式来使得模型更合适。
也可以使用:
3.7 正规方程:
通过下面方程可以计算参数:
注:当正规方程中矩阵出现不可逆时,我们通常采用剔除线性相关的两个特征的其中一个;或是使用np.linalg.pinv()
4 代码实战:
- 数据:
我们的数据有两个特征变量,我们设x为population,y为profit
- 观察数据分布情况:
import tensorflow as tf
import numpy as np
from matplotlib import pyplot as plt
import pandas as pd
def loadData(file_name):
"""读取数据
Param:
file_name:文件存放路径
return dataset_x,dataset_y"""
dataset = pd.read_csv(file_name,names=['population','profit'])
dataset_x = dataset['population']
dataset_y = dataset['profit']
return dataset_x,dataset_y
def Show():
file_name = 'E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex1-linear regression/ex1data1.txt'
dataset_x,dataset_y = loadData(file_name)
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
plt.figure(figsize=(20,10),dpi=70)
plt.scatter(dataset_x,dataset_y,color='orange',s=60)
plt.xlabel('Population',fontsize=12,fontweight='bold')
plt.ylabel('Profit',fontsize=12,fontweight='bold')
plt.title('Data Distribution',fontsize=16,fontweight='bold')
plt.show()
if __name__=='__main__':
Show()
- 定义一个函数,将x,y分布取出:
def get_x(data):
"""插入一列x0=1,并且输出narray型的X
Params:
data:读取的数据
return:
narray型的X"""
data_x = data['population'] #取出x的数据
n = data_x.shape[0] #获取行数
x0 = pd.DataFrame({'X0':np.ones(n)})
#新建一个DataFrame列表用来concat(注:concat不能用narray直接组合)
X = pd.concat([x0,data_x],axis=1)
return np.array(X)
def get_y(data):
Y = data['profit']
return np.array(Y)
- 计算代价函数:
def j(X,Y,weight):
"""计算代价函数
Params:
X:get_x返回的数据
Y:get_y返回的数据
weight:初始化的未知参数
return:
j_:对应的代价函数"""
m = X.shape[0]
inner = X@weight - Y #@想当与矩阵乘法
square_sum = inner.T @inner #.T相当于转置
j_ = square_sum/(2*m)
return j_
if __name__=='__main__':
X = get_x(data)
Y = get_y(data)
n = X.shape[1]
weight=np.zeros(n)
j_=j(X,Y,weight)
print(j_)
结果为:
- 计算梯度下降函数:
def gradDscent(X,Y,weight):
m=X.shape[0]
inner = X.T @(X@weight-Y)
return inner/m
- 批量梯度下降:
def batch_gradient_decent(weight,X,Y,epoch,alpha=0.01):
"""批量梯度下降,获取最优参数,和代价函数列表来确定合适的迭代次数
Params:
weight:初始化的参数
X:get_x返回的数据
Y:get_y返回的数据
epoch:迭代次数
alpha:步长
return:
j_:存放所有代价函数值的列表
weight_:最优参数"""
j_ = [j(X,Y,weight)] #新建一个列表
m,n = X.shape
weight_ = weight.copy() #复制一个以防混淆
for i in range(epoch): #进入迭代
weight_ = weight_ - alpha*gradDscent(X,Y,weight_)
j_.append(j(X,Y,weight_))
return j_,weight_
结合:
import tensorflow as tf
import numpy as np
from matplotlib import pyplot as plt
import pandas as pd
def get_x(data):
"""插入一列x0=1,并且输出narray型的X
Params:
data:读取的数据
return:
narray型的X"""
data_x = data['population'] #取出x的数据
n = data_x.shape[0] #获取行数
x0 = pd.DataFrame({'X0':np.ones(n)})
#新建一个DataFrame列表用来concat(注:concat不能用narray直接组合)
X = pd.concat([x0,data_x],axis=1)
return np.array(X)
def get_y(data):
Y = data['profit']
return np.array(Y)
def j(X,Y,weight):
"""计算代价函数
Params:
X:get_x返回的数据
Y:get_y返回的数据
weight:初始化的未知参数
return:
j_:对应的代价函数"""
m = X.shape[0]
inner = X@weight - Y #@想当与矩阵乘法
square_sum = inner.T @inner #.T相当于转置
j_ = square_sum/(2*m)
return j_
def gradDscent(X,Y,weight):
m=X.shape[0]
inner = X.T @(X@weight-Y)
return inner/m
def batch_gradient_decent(weight,X,Y,epoch,alpha=0.01):
"""批量梯度下降,获取最优参数,和代价函数列表来确定合适的迭代次数
Params:
weight:初始化的参数
X:get_x返回的数据
Y:get_y返回的数据
epoch:迭代次数
alpha:步长
return:
j_:存放所有代价函数值的列表
weight_:最优参数"""
j_ = [j(X,Y,weight)] #新建一个列表
m,n = X.shape
weight_ = weight.copy() #复制一个以防混淆
for i in range(epoch): #进入迭代
weight_ = weight_ - alpha*gradDscent(X,Y,weight_)
j_.append(j(X,Y,weight_))
return j_,weight_
if __name__ == '__main__':
data = pd.read_csv('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex1-linear regression/ex1data1.txt',names=['population','profit'])
X=get_x(data)
Y=get_x(data)
n = X.shape[1]
weight = np.zeros(n)
j_,weight_=batch_gradient_decent(weight,X,Y,300,alpha=0.01)
Y = np.arange(401)
plt.plot(Y,j_)
plt.show()
- 画出拟合线:
b = weight_[0]#获得截距
m = weight_[1]#获得斜率
y = data.population*m+b
plt.scatter(data.population,data.profit,color = 'red',label='Training data')
plt.plot(data.population,y,color='orange',label='Prediction')
plt.legend(loc=2)
plt.show()