机器学习-单变量线性回归
单变量线性回归学习算法流程图
创建模型
-
我们通过一个例子作为开始,这个例子就是预测房价的例子。我们要使用一个数据集,数据集包含某地的住房价格。假设你有一朋友正想出售自己面积为1500平方英尺的房子,你要告诉他这房子可以卖多少钱。这时你就需构建一个模型,从这个数据集来看这或许是条直线,从图中你可以对你朋友说这房子可以卖28万美元左右。
-
这就是监督学习的一个例子,其这所以称之为监督学习是因为对于每个数据而言,我们预先给出了“正确答案”,即告诉我们根基我们所拥有的数据,我们可以得出房屋的实际价格。
-
对于这个例子更为具体而言。这是一个回归问题,回归一词指的是我们根据已有的数据预测出一个正确的输出值。更进一步来说,在监督学习中我们都会拥有一个数据集,这个数据集称为训练集。我们将在以后用如下标记描述回归问题:
-
我们通常使用h(hypothesis)表示一个函数。在预测房价的例子中,x对应房屋面积,y对应房屋价格,根据监督学习我们可以构建一个函数表达式h:
hθ(x) = θ0 + θ1X -
我们将这种可以构建出线性函数的模型称为线性回归模型。在这里只有一个特征变量X,因此我们称这种单一变量模型为单变量线性回归。
代价函数
-
在线性回归中我们有一个像这样的训练集,代表了训练样本的数量,比如 。而我们的假设函数,也就是用来进行预测的函数,是这样的线性函数形式:hθ(x) = θ0 + θ1X
-
接下来要做的便是为我们的模型选择合适的参数(parameters)θ0 和 θ1,选择的参数决定了我们得到的直线相对于我们的训练集的准确程度,模型所预测的值与训练集中实际值之间的差距(下图中蓝线所指)就是建模误差(modeling error)。
我们的目标便是选择出可以使得建模误差的平方和能够最小的模型参数。 即使得代价函数最小。
-
代价函数三维空间示意图
则可以看出在三维空间中存在一个使得J(θ0 +θ1 )最小的点。 -
代价函数也被称作平方误差函数,有时也被称为平方误差代价函数。我们之所以要求出误差的平方和,是因为误差平方代价函数,对于大多数问题,特别是回归问题,都是一个合理的选择。还有其他的代价函数也能很好地发挥作用,但是平方误差代价函数可能是解决回归问题最常用的手段了。
梯度下降
- 梯度下降是一个用来求函数最小值的算法,我们将使用梯度下降算法来求出代价函数J(θ0,θ1) 的最小值。
- 梯度下降背后的思想是:开始时我们随机选择一个参数的组合(θ0,θ1),计算代价函数,然后我们寻找下一个能让代价函数值下降最多的参数组合。
批量梯度下降算法
- α是学习率(learning rate),大于0的一个很小经验值,它决定沿着能让代价函数下降的程度有多大。
- 每一次都同时让所有的参数减去学习速率乘以代价函数的导数。
- “批量梯度下降”,指的是在梯度下降的每一步中,都要用到了所有的训练样本,因为代价函数是所有训练样本估计误差的平方和。
学习率α太小或太大的影响
python代码实现
import numpy as np
import matplotlib.pyplot as plt
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 读取数据
train_data = np.loadtxt(r'D:\八维学习资料\机器学习\day03\train_fish.txt',delimiter=',')
test_data = np.loadtxt(r'D:\八维学习资料\机器学习\day03\test_fish.txt',delimiter=',')
print(train_data.shape,test_data.shape)
# 数据的提取
train_X,train_y = train_data[:,:-1],train_data[:,-1]
test_X,test_y = test_data[:,:-1],test_data[:,-1]
# 数据的预处理
def preProcess(X,y):
m = X.shape[0]
#数据的初始化
X = np.c_[np.ones(m),X]
y = np.c_[y]
return X,y
train_X,train_y = preProcess(train_X,train_y)
test_X,test_y = preProcess(test_X,test_y)
# 定义模型
def model(X,theta):
h = np.dot(X,theta)
return h
# 定义代价函数
def costFunc(h,y):
m = len(y)
J = (1.0/(2 * m)) * np.sum(np.square(h - y))
return J
# 实现梯度下降函数
def graDesc(X,y,alpha = 0.01,iter_num = 2000):
m,n = X.shape
theta = np.zeros((n,1)) #初始化theta
J_history = np.zeros(iter_num) #初始化代价值
for i in range(iter_num):
# 调用模型获得预测值
h = model(X,theta)
# 调用代价函数得到每一次循环的带价值
J_history[i] = costFunc(h,y)
# if i % 100 == 0:
# print(J_history[i])
deltaTheta = (1.0/m) * np.dot(X.T,h - y)
theta -= alpha * deltaTheta
return J_history,theta
# 定义求精度函数
def score(h,y):
u = np.sum(np.square(h - y))
v = np.sum(np.square(y - np.mean(y)))
score = 1 - u/v
return score
J_history,theta = graDesc(train_X,train_y,alpha=0.001,iter_num=2000)
print(theta)
# 求训练集的预测结果
train_h = model(train_X,theta)
# 求测试集的预测结果
test_h = model(test_X,theta)
# 训练街的精度
print('训练集的精度=%.2f'%score(train_h,train_y))
print('测试集的精度=%.2f'%score(test_h,test_y))
# 画代价曲线
plt.title('代价曲线')
plt.plot(J_history)
plt.xlabel('iter_num')
plt.ylabel('J_history')
plt.show()
# 散点图和回归方程
plt.title('测试集散点图和回归方程')
plt.scatter(test_X[:,1],test_y,label='测试样本',c='r')
test_X_min,test_X_max = np.min(test_X[:,1]),np.max(test_X[:,1])
test_y_min,test_y_max = theta[0] + theta[1]*test_X_min,theta[0]+theta[1]*test_X_max
plt.plot([test_X_min,test_X_max],[test_y_min,test_y_max],label='回归方程')
plt.legend()
plt.show()
# 画真实值和预测值的对比图
plt.title('真实值/预测值对比图')
plt.scatter(test_y,test_y,label='真实值散点图')
plt.scatter(test_y,test_h,label='预测值散点图')
plt.xlabel('真实值')
plt.ylabel('真实值/预测值')
plt.legend()
plt.show()
效果展示如下