目前为止,咱们探讨了单变量/特征的回归模型,如今咱们对房价模型增长更多的特征,例如房间数楼层等,构成一个含有多个变量的模型.。python
例如:算法
x(1) = [40, 1, 1, 10] x(2) = [96, 2, 1, 5] x(3) = [135, 3, 2, 20]
例如:dom
x(1)1 = 40 x(1)2 = 1 .......
import numpy as np # 1). 模拟数据 X1 = 2 * np.random.randn(100, 1) X2 = 4 * np.random.rand(100, 1) X3 = 6 * np.random.rand(100, 1) y = 4 + 3 * X1 + 4 * X2 + 5 * X3 + np.random.randn(100, 1) # 2). 实现梯度降低算法 # np.c_是将数据组合成向量格式: (n, 1) (n,1) = (n, 2) X_b = np.c_[np.ones((100, 1)), X1, X2, X3] # 初始化theta的值, 须要计算四个theta的值; theta = np.random.randn(4, 1) # 设置学习率和收敛次数 learning_rate = 0.1 n_iterations = 1000 # 根据公式计算 for iteration in range(n_iterations): # 梯度降低公式 = 1/样本数 * (预测值 - 真实值) *Xi gradients = 1 / 100 * X_b.T.dot(X_b.dot(theta) - y) # theta = theta - 学习率 * 梯度值 theta = theta - learning_rate * gradients print(theta)
在咱们面对多维特征问题的时候,咱们要保证这些特征都具备相近的尺度,这将帮助梯度降低算法更快地收敛。而特征缩放是为了确保特征在一个数量级上。 函数
以房价问题为例,假设咱们使用两个特征,房屋的尺寸和房间的数量,其中x1 = 房屋面积(0-400 m2), x2 = 卧室数量(1-5), 以两个参数分别为横纵坐标,绘制代价函数的等高线图能,看出图像会显得很扁,梯度降低算法须要很是屡次的迭代才能收敛。学习
解决方法一:测试
x1 = 房屋面积 / 400
x2 = 卧室数量 / 5字体
也能够把最大值换成标准差,或者最大值 – 最小值。优化
梯度降低算法收敛所须要的迭代次数根据模型的不一样而不一样,咱们不能提早预知,咱们能够绘制迭代次数和代价函数的图表来观测算法在什么时候趋于收敛。
梯度降低算法的每次迭代受到学习率的影响,spa
尝试在以下的数值中选择α : …, 0.001, 0.003, 0.01, 0.03, 0.1, 0.3, 1,…
设计
如何选择?
随机梯度降低思想:把m个样本分红m份,每次用1份作梯度降低;也就是说,当有m个样本时,批梯度降低只能作一次梯度降低,可是随机梯度降低能够作m次。
import numpy as np import random X = 2 * np.random.rand(100, 1) Y = 4 + 3 * X + np.random.randn(100, 1) X_b = np.c_[np.ones((100, 1)), X] # 每轮epochs处理m个样本; n_epochs = 1000 # 学习率 a0 = 0.1 # 定义衰减率 decay_rate = 1 def learning_schedule(epoch_num): """ 定义一个学习率衰减的函数 """ return (1.0 / (decay_rate * epoch_num + 1)) * a0 # 初始化theta值 theta = np.random.randn(2, 1) # 初始化随机值 num = [i for i in range(100)] m = 100 for epoch in range(n_epochs): rand = random.sample(num, 100) for i in range(m): random_index = rand[i] xi = X_b[random_index:random_index + 1] yi = Y[random_index:random_index + 1] # 随机梯度降低值 gradients = xi.T.dot(xi.dot(theta) - yi) # 学习率 learning_rate = learning_schedule(epoch+1) theta = theta - learning_rate * gradients print(theta)
随机梯度降低会丧失向量带来的加速,因此咱们不会太用随机梯度降低。
import numpy as np import random X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1) X_b = np.c_[np.ones((100, 1)), X] # print(X_b) n_epochs = 500 a = 0.03 m = 100 num = [i for i in range(100)] theta = np.random.randn(2, 1) batch_num = 5 batch_size = m // 5 # epoch 是轮次的意思,意思是用m个样本作一轮迭代 for epoch in range(n_epochs): # 生成100个不重复的随机数 for i in range(batch_num): start = i*batch_size end = (i+1)*batch_size xi = X_b[start:end] yi = y[start:end] gradients = 1/batch_size * xi.T.dot(xi.dot(theta)-yi) print(a) learning_rate = a theta = theta - learning_rate * gradients print(theta)
在作Mini-batch的时候,由于噪声的缘由,可能训练结果不是收敛的,而是在最低点周围晃动,若是咱们要解决这个问题,那咱们就须要减小学习率,让他在尽可能小的范围内晃动
1 epoch = 1 次遍历全部的数据
import numpy as np import random X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1) X_b = np.c_[np.ones((100, 1)), X] # print(X_b) n_epochs = 500 t0, t1 = 5, 50 m = 100 num = [i for i in range(100)] def learning_schedule(t): return float(t0) / (t + t1) theta = np.random.randn(2, 1) batch_num = 5 batch_size = m // 5 # epoch 是轮次的意思,意思是用m个样本作一轮迭代 for epoch in range(n_epochs): # 生成100个不重复的随机数 for i in range(batch_num): start = i*batch_size end = (i+1)*batch_size xi = X_b[start:end] yi = y[start:end] gradients = 1/batch_size * xi.T.dot(xi.dot(theta)-yi) learning_rate = learning_schedule(epoch*m + i) theta = theta - learning_rate * gradients print(theta)
过拟合的问题出如今变量(θ)过多的时候,这时候咱们没有更多的数据去拟合模型,虽然损失函数的值基本接近于0。
房价预测时, 假设咱们不知道房屋面积,可是知道房屋的长宽。
注:若是咱们采用多项式回归模型,在运行梯度降低算法前,特征缩放很是有必要。
首先, 咱们能够在损失函数中,加入关于theta3和theta4的项, 迫使若损失函数想要最小化, 必须让theta3和theta4尽量的小。
而后正则化, 公式以下图:
""" 岭回归 方法一: 岭回归运用了L2正则化 """ import numpy as np from sklearn.linear_model import Ridge from sklearn.linear_model import SGDRegressor X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1) # alpha是惩罚项里的alpha, solver处理数据的方法,auto是根据数据自动选择,svd是解析解,sag就是随机梯度降低 ridge_reg = Ridge(alpha=1, solver='auto') # 学习过程 ridge_reg.fit(X, y) # 预测 print(ridge_reg.predict([[1.5], [2], [2.5]])) # 打印截距 print(ridge_reg.intercept_) # 打印系数 print(ridge_reg.coef_) """ 方法二: 岭回归和sgd & penalty=2是等价的 """ sgd_reg = SGDRegressor(penalty='l2') sgd_reg.fit(X, y.ravel()) print(sgd_reg.predict([[1.5], [2], [2.5]])) # 打印截距 print("W0=", sgd_reg.intercept_) # 打印系数 print("W1=", sgd_reg.coef_)
""" Lasso 回归 Lasso用的是l1的正则化 """ import numpy as np from sklearn.linear_model import Lasso from sklearn.linear_model import SGDRegressor X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1) lasso_reg = Lasso(alpha=0.15) lasso_reg.fit(X, y) print(lasso_reg.predict([[1.5]])) print(lasso_reg.coef_) sgd_reg = SGDRegressor(penalty='l1', n_iter=1000) sgd_reg.fit(X, y.ravel()) print(sgd_reg.predict([[1.5]])) print(sgd_reg.coef_)
import numpy as np from sklearn.linear_model import ElasticNet X = 2 * np.random.rand(100, 1) Y = 4 + 3 * X + np.random.randn(100, 1) elastic_reg = ElasticNet(alpha=0.15, l1_ratio=0.5) elastic_reg.fit(X, Y) print(elastic_reg.predict([[1.5]])) print(elastic_reg.coef_) print(elastic_reg.intercept_) from sklearn.linear_model import SGDRegressor elastic_reg = SGDRegressor(penalty='elasticnet') elastic_reg.fit(X, Y) print(elastic_reg.predict([[1.5]])) print(elastic_reg.coef_)
梯度降低:
正规方程:
总结:根据经验,当特征数量到10000的时候,是会换成梯度降低比较好
import numpy as np import matplotlib.pyplot as plt from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression # 1). 数据准备; # 样本数 m = 100 X = 6 * np.random.randn(m, 1) - 3 Y = 0.5 * X ** 2 + X + 2 + np.random.randn(m, 1) # 2). 处理 # 2-1). 将一个高阶方程转化为一个一阶方程;(多元线性回归) # degree:用几维处理数据; poly_features = PolynomialFeatures(degree=2, include_bias=False) # fit_transform === fit() + transform(), 其中transform就是用来作归一化的; X_poly = poly_features.fit_transform(X, Y) # 2-2). 处理一阶方程 line_reg = LinearRegression() line_reg.fit(X_poly, Y) print(line_reg.coef_) print(line_reg.intercept_)
import numpy as np import matplotlib.pyplot as plt from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression # 1). 数据准备; # 样本数 m = 100 X = 6 * np.random.randn(m, 1) - 3 Y = 7 * X ** 2 + 5 *X + 2 + np.random.randn(m, 1) # plt.plot(X, Y, 'b.') # plt.show() # 设置图像维度及线条的字体显示 d = {1: 'g-', 2: 'r.', 10: 'y*'} # d = {2: 'g-'} for i in d: # 2). 处理 # 2-1). 将一个高阶方程转化为一个一阶方程;(多元线性回归) # degree:用几维处理数据; poly_features = PolynomialFeatures(degree=i, include_bias=False) # fit_transform === fit() + transform(), 其中transform就是用来作归一化的; X_poly = poly_features.fit_transform(X) print(X_poly) # 2-2). 处理一阶方程 line_reg = LinearRegression() line_reg.fit(X_poly, Y) print(line_reg.coef_) print(line_reg.intercept_) y_predict = line_reg.predict(X_poly) plt.plot(X_poly[:, 0], y_predict, d[i]) plt.show()