之前的线性回归模型预测波士顿房价的主要是利用Python的库函数来,也就是调包的。试考完了,就开始从头学了。这个逻辑似乎有点奇怪,不过因为平时做实验都是调包总觉得味同嚼蜡,不够味道。
回到正题。线性回归是利用线性函数对自变量与因变量建立线性组合关系的回归分析。
一个自变量对应一个因变量,则是一元线性回归;多个自变量则是多元线性回归。
也就是使得输入数据集D中的数据满足其中就是线性回归模型的参数(超参数)。
线性回归的目标就是使得 恒成立。
不过,在计算过程中总会有数据不是完全满足线性的要求,但是又要使得尽可能多的数据符合线性回归模型,使得预测值尽可能接近真实值。
于是就要求有损失函数,来使得输入数据利用线性回归模型预测更加准确。主要的做法就是利用方差来计算预测值与真实值之间的“差距”,尽可能降低方差,也就是选取输入数据中更加符合线性关系的数据来构建线性回归模型。
损失函数Loss: (此处2n是方便求导),
也就是求。
具体计算就是利用梯度下降的方法来计算:.
其中α为学习率,用来表示迭代时α的更新速度。这样每次迭代就使得的Loss越来越小,即收敛。
这里选用MBGD(Mini Batch Gradient Descent)批尺寸梯度下降算法。
m为 data size,n 为Mini Batch size,则上述梯度下降公式计算如下:
MBGD算法的基本思想:将训练集随机样本划分成n个等分小样本,每次迭代遍历每个小样本,计算小批量样本的梯度平均值,并根据计算的平均值调整超参数θ。
Python代码部分:
MBGD算法
def MBGD(self,alpha,batch_size): """ 这是利用MBGD算法进行一次迭代调整参数的函数 :param alpha: 学习率 :param batch_size: 小样本规模 """ # 首先将数据集随机打乱,减小数据集顺序对参数调优的影响 shuffle_sequence = self.Shuffle_Sequence() self.InputData = self.InputData[shuffle_sequence] self.Result = self.Result[shuffle_sequence] # 遍历每个小批量样本 for start in np.arange(0, len(shuffle_sequence), batch_size): # 判断start+batch_size是否大于数组长度, # 防止最后一组小样本规模可能小于batch_size的情况 end = np.min([start + batch_size, len(shuffle_sequence)]) # 获取训练小批量样本集及其标签 mini_batch = shuffle_sequence[start:end] Mini_Train_Data = self.InputData[mini_batch] Mini_Train_Result = self.Result[mini_batch] # 定义梯度增量数组 gradient_increasment = [] # 对小样本训练集进行遍历,利用每个小样本的梯度增量的平均值对模型参数进行更新 for (data,result) in zip(Mini_Train_Data,Mini_Train_Result): # 计算每组input_data的梯度增量,并放入梯度增量数组 g = (result - data.dot(self.Theta)) * data gradient_increasment.append(g) # 按列计算每组小样本训练集的梯度增量的平均值,并改变其形状 avg_g = np.average(gradient_increasment, 0) avg_g = avg_g.reshape((len(avg_g), 1)) # 更新模型参数theta self.Theta = self.Theta + alpha * avg_g
MBGD训练
def train_MBGD(self,iter,batch_size,alpha): """ 这是利用MBGD算法迭代优化的函数 :param iter: 迭代次数 :param batch_size: 小样本规模 :param alpha: 学习率 """ # 定义训练损失数组,记录每轮迭代的训练数据集的训练损失 Cost = [] # 开始进行迭代训练 for i in range(iter): # 利用学习率alpha,结合MBGD算法对模型进行训练 self.MBGD(alpha,batch_size) # 记录每次迭代的训练损失 Cost.append(self.Cost()) Cost = np.array(Cost) return Cost
对训练数据进行测试:
def test(self,test_data): """ 这是对测试数据集的线性回归预测函数 :param test_data: 测试数据集 """ # 定义预测结果数组 predict_result = [] # 对测试数据进行遍历 for data in test_data: # 预测每组data的结果 predict_result.append(self.predict(data)) predict_result = np.array(predict_result) return predict_result
对测试数据进行预测
def predict(self,data): """ 这是对一组测试数据预测的函数 :param data: 测试数据 """ # 对测试数据加入1维特征,以适应矩阵乘法 tmp = [1.0] tmp.extend(data) data = np.array(tmp) # 计算预测结果,计算结果形状为(1,),为了分析数据的方便 # 这里只返矩阵的第一个元素 predict_result = data.dot(self.Theta)[0] return predict_result
参考资料:
[1]《机器学习入门——基于数学原理的Python实战》
[2]https://github.com/Daipuwei/Introduction-to-Machine-Learning-Based-on-Mathematical-Principles-with-Python/tree/master/