活动地址:CSDN21天学习挑战赛
前言
环境:
python3.7
IDEA
机器学习基本思路:
- 推导公式进行建模
- 优化模型
- 评估系数
- 根据模型进行预测
回归
1. 案例
一元线性回归的例子引出线性回归模型:
1920年汽车速度与刹车距的数据,现在,我们想研究速度与刹车距离之间到底有什么样的关系。
绘制散点图
# 1.收集数据 data_cars = pd.read_csv("../data/cars.csv",usecols = ["speed","dist"]) print(data_cars.head()) # 2.可视化 speed = data_cars["speed"] dist = data_cars["dist"] plt.scatter(speed,dist) # 散射 plt.title("Scatter plot of vehicle speed and braking distance") plt.show()
呈现线性关系:
为了使预测更为精准
从图像直观描述,就是使寻找一条直线,使得所有样本点到直线的距离之和最短,如图7.1.2所示:
以下在机器学习中称为损失函数:
损失函数
损失函数:简而言之,就是实际偏离模型的数据点与预期在模型上的数据点的差值,规律总结而成的函数。
我们可以通过直接法和迭代法两种方式对该损失函数进行优化,进而得到使损失函数最小的回归系数。下面,我们分别用这两种方法进行求解。
直接法
直接法,就是直接给出优化问题的最优解,并不是所有的优化问题都可以用直接法得到最优解,如果要
使用直接法,损失函数需要满足两个条件:
1. 损失函数为凸函数; (曲线是凹状或者凸状)
2. 损失函数为解析解,即通过严格的公式所求得的解。
凸函数定义:
图7.1.3 凸函数曲线图
python代码:
## 2.2 损失函数 import sympy #设定回归系数 alpha, beta = sympy.symbols("alpha beta") #设定损失函数 L = 0.5* np.sum((dist - beta*speed - alpha)**2) #求偏导 print(sympy.diff(L, alpha)) #50.0*alpha + 770.0*beta - 2149.0 print(sympy.diff(L, beta)) #770.0*alpha + 13228.0*beta - 38482.0 f1 = sympy.diff(L, alpha) f2 = sympy.diff(L, beta) ### 求解线性方程组 outcome = sympy.solve([f1, f2], [alpha, beta]) print(outcome) #{alpha: -17.5790948905109, beta: 3.93240875912409} 最优解
{alpha: -17.5790948905109, beta: 3.93240875912409} 最优解
我们将直线 y = 3.932x+ -17.570
绘制在车速与刹车距离散点图中,如图7.1.5所示。
### 绘图 alpha_num = outcome[alpha] beta_num = outcome[beta] dist_pre = beta_num*speed + alpha_num plt.scatter(speed, dist) plt.plot(speed, dist_pre, c = "r") plt.title("Fitting results") plt.show()
迭代法
很多情况都是非凸形的 没法使用直接法进行优化 所以我们可以使用迭代法求解。迭代法是一种不断用变量的旧值递推新值的过程,即迭代的用旧值修正对最优解的估计。
这里,我们使用迭代法中的小批量梯度下降法解决问题:
对于我们的问题,小批量梯度下降法的过程如下:
- 确定要求解的模型参数为 α,β ;
- 定义小批量梯度下降法的损失函数:
- 求解梯度,并定义递推关系:
在[0, 10)中按照均匀分布随机产生alpha和beta的初始值,定义学习率 和 均为0.02,定义迭代次数
为20000次; - 迭代,迭代完成输出最后的模型参数。
#迭代法 import random #定义递推关系,更新迭代变量 def update_var(old_alpha, old_beta, y, x, learning_rate): len_x = len(x) alpha_delta = np.sum(-(y - old_beta*x - old_alpha))/len_x beta_delta = np.sum(-x*(y - old_beta*x - old_alpha))/len_x new_alpha = old_alpha - learning_rate*alpha_delta new_beta = old_beta - learning_rate*beta_delta return (new_alpha, new_beta) #迭代 def iterative_func(y, x, start_alpha, start_beta, learning_rate, iterative_num, sample_num): alpha_list = [] beta_list = [] alpha = start_alpha beta = start_beta num_list = list(range(1, len(y)+1)) for i in range(iterative_num): alpha_list.append(alpha) beta_list.append(beta) random.shuffle(num_list) index = num_list[:sample_num] alpha, beta = update_var(alpha, beta, y[index], x[index], learning_rate) # print("alpha: {}, beta:{}".format(alpha, beta)) return (alpha_list, beta_list) #在[0, 10)之间按照均匀分布随机产生alpha和beta的初始值 start_alpha = np.random.random()*10 start_beta = np.random.random()*10 #设置学习率为0.01,迭代次数为500次,每次计算8个数据 learning_rate = 0.002 iterative_num = 20000 sample_num = 16 alpha_list, beta_list = iterative_func(dist, speed, start_alpha, start_beta, learning_rate, iterative_num, sample_num)
最后会发现直接法和迭代法 答案相近
最后绘制α和β变化:
...代码接上... #写出 import csv parameter_data = zip(alpha_list, beta_list) with open("./outcome/gradient_descent_parameter.csv", 'w', newline = '') as f: csv_writer = csv.writer(f) csv_writer.writerow(["alpha","beta"]) csv_writer.writerows(parameter_data) #绘图 plt.subplot(121) plt.plot(alpha_list) plt.title("alpha change process") plt.subplot(122) plt.plot(beta_list) plt.title("beta change process") plt.show()
学习率:影响变化稳定的因素,我们可以设置其学习率随着迭代次数增加逐渐递减,来缓解这种现象
样本数:
迭代次数:
评估数据好坏
直接法求得的回归系数估计值进行评价,即计算其 R^2:
#判定系数R2 dist_pre = beta_num*speed + alpha_num dist_mean = np.mean(dist) R_2 = np.sum((dist_pre - dist_mean)**2)/np.sum((dist - dist_mean)**2) print(R_2) #0.651079380758251 #预测 new_speed = pd.Series([10, 20, 30]) new_dist_pre = beta_num*new_speed + alpha_num print(new_dist_pre)
结果R^2得到0.65107938
预测
利用我们的模型对结果进行预测。
我们依然采用直接法求得的回归系数估计值,对新的样本进行预测。
假设新记录的一批车辆的车速分别为10, 20, 30,利用python,我们可以得到刹车距离的预测值为21.745,61.069,100.393。