机器学习详解(3):线性回归之代码详解
文章目录
- 1 数据预处理
- 2 构建线性回归模型并绘制回归线
- 初始化方法
- 前向传播:forward_propagation
- 代价函数:cost_function
- 反向传播:backward_propagation
- 参数更新:update_parameters
- 训练方法:train
- 代码运行结果
- 3 使用Pytorch实现线性回归
- 4 扩展:正则化
- 4.1 正则化解释
- 4.2 正则化实例
- 5 总结
上一节中,我们介绍了 线性回归的原理,那么这篇文章就来用一个实际的例子来看一下如何用代码实现线性回归。
1 数据预处理
我们事先准备好了数据,保存在csv文件中,大致的数据结构如下,文件中有701行数据。
首先导入我们本节需要使用的库:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.axes as ax
from matplotlib.animation import FuncAnimation
接下来读取文件、预处理,然后分割一下训练集和测试集。
(1)读取文件并删除空行
pd.read_csv
用来读取csv文件,data.dropna()
删除 DataFrame 中包含缺失值的行。此操作会移除任何含有 NaN
或空值的记录。
csv_dir = '/content/drive/MyDrive/learning/data_for_lr.csv'
data = pd.read_csv(csv_dir)# Drop the missing values
data = data.dropna()
(2)分割训练集和测试集
# training dataset and labels
train_input = np.array(data.x[0:500]).reshape(500, 1)
train_output = np.array(data.y[0:500]).reshape(500, 1)# valid dataset and labels
test_input = np.array(data.x[500:700]).reshape(199, 1)
test_output = np.array(data.y[500:700]).reshape(199, 1)
data.x
和data.y
:使用pd.read_csv(csv_dir)
读取 CSV 文件后,Pandas 会将 CSV 文件的每一列名称作为 DataFrame 中的列名,对应csv中的两列的列名x
和y
- 为什么要转化为numpy格式?
data
是一个Pandas DataFrame
对象,机器学习模型通常要求输入数据为 NumPy 数组,因为它提供高效的矩阵运算和更广泛的数学操作支持。此外,NumPy 与主流机器学习框架(如 Scikit-learn、TensorFlow)更兼容,性能优于 Pandas 数据结构。
- 以训练集为例:
data.x[0:500]
表示取数据集中第 0 到 499 行的x
列(假设 DataFrame 中有名为x
的列)。reshape(500, 1)
将一维数组调整为形状为 500 × 1 500 \times 1 500×1 的二维数组,便于与机器学习模型输入格式匹配。- 机器学习模型的输入通常是二维数组,形状为 ( n samples , n features ) (n_{\text{samples}}, n_{\text{features}}) (nsamples,nfeatures),表示 n samples n_{\text{samples}} nsamples 个样本,每个样本有 n features n_{\text{features}} nfeatures 个特征。
- 这里的输入特征只有一个x,输出特征只有一个y,所以两个数组都reshape成 500 × 1 500 \times 1 500×1
2 构建线性回归模型并绘制回归线
步骤:
- 在前向传播中,应用线性回归函数 Y = m x + c Y = mx + c Y=mx+c,其中参数 m m m 和 c c c 初始赋值为随机值。
- 然后编写一个函数用于计算损失函数,即均值。
现在我们打算实现一个LinearRegression类,即一个简单的线性回归模型,通过梯度下降进行参数优化,包括前向传播、代价函数计算、后向传播以及参数更新等关键步骤。
初始化方法
def __init__(self): self.parameters = {}
- 初始化参数字典
self.parameters
,即声明并初始化一个空字典,用于存储回归系数 m m m 和截距 c c c。
前向传播:forward_propagation
前向传播是机器学习模型从输入数据经过模型参数(如权重和偏置)计算输出预测值的过程,例如线性回归中通过公式 y = m x + c y = mx + c y=mx+c 计算结果。它用于生成预测值,并为损失函数计算提供基础。
def forward_propagation(self, train_input): m = self.parameters['m'] c = self.parameters['c'] predictions = np.multiply(m, train_input) + c return predictions
- 通过公式 y = m x + c y = mx + c y=mx+c 计算预测值,训练输入为 t r a i n _ i n p u t train\_input train_input,输出为预测值 p r e d i c t i o n s predictions predictions。
代价函数:cost_function
def cost_function(self, predictions, train_output): cost = np.mean((train_output - predictions) ** 2) return cost
- 使用均方误差(MSE)计算损失: C o s t = 1 n ∑ ( y a c t u a l − y p r e d i c t e d ) 2 Cost = \frac{1}{n} \sum (y_{actual} - y_{predicted})^2 Cost=n1∑(yactual−ypredicted)2。
np.mean
用于计算数组元素的平均值
- 输入:预测值 p r e d i c t i o n s predictions predictions 和训练输出 t r a i n _ o u t p u t train\_output train_output。
- 输出:损失值 c o s t cost cost。
反向传播:backward_propagation
def backward_propagation(self, train_input, train_output, predictions): derivatives = {} df = (predictions - train_output) dm = 2 * np.mean(np.multiply(train_input, df)) dc = 2 * np.mean(df) derivatives['dm'] = dm derivatives['dc'] = dc return derivatives
- 计算梯度,在上一篇文章中我们计算了下面两个公式:
- 对 m m m 的梯度: ∂ C o s t ∂ m = 2 n ∑ ( y p r e d i c t e d − y a c t u a l ) ⋅ x i n p u t \frac{\partial Cost}{\partial m} = \frac{2}{n} \sum (y_{predicted} - y_{actual}) \cdot x_{input} ∂m∂Cost=n2∑(ypredicted−yactual)⋅xinput。
- 对 c c c 的梯度: ∂ C o s t ∂ c = 2 n ∑ ( y p r e d i c t e d − y a c t u a l ) \frac{\partial Cost}{\partial c} = \frac{2}{n} \sum (y_{predicted} - y_{actual}) ∂c∂Cost=n2∑(ypredicted−yactual)。
- 输入:训练输入 t r a i n _ i n p u t train\_input train_input,训练输出 t r a i n _ o u t p u t train\_output train_output,预测值 p r e d i c t i o n s predictions predictions。
- 输出:包含梯度 d m dm dm 和 d c dc dc 的字典。
参数更新:update_parameters
def update_parameters(self, derivatives, learning_rate): self.parameters['m'] = self.parameters['m'] - learning_rate * derivatives['dm'] self.parameters['c'] = self.parameters['c'] - learning_rate * derivatives['dc']
- 使用梯度下降法更新参数,在上一篇文章中我们提到要使用下面的公式来更新参数:
- m = m − α ⋅ ∂ C o s t ∂ m m = m - \alpha \cdot \frac{\partial Cost}{\partial m} m=m−α⋅∂m∂Cost。
- c = c − α ⋅ ∂ C o s t ∂ c c = c - \alpha \cdot \frac{\partial Cost}{\partial c} c=c−α⋅∂c∂Cost。
- 输入:梯度字典 d e r i v a t i v e s derivatives derivatives 和学习率 l e a r n i n g _ r a t e learning\_rate learning_rate。
训练方法:train
完整代码如下:
def train(self, train_input, train_output, learning_rate, iters): # Initialize random parameters self.parameters['m'] = np.random.uniform(0, 1) * -1self.parameters['c'] = np.random.uniform(0, 1) * -1# Initialize loss self.loss = [] # Initialize figure and axis for animation fig, ax = plt.subplots() x_vals = np.linspace(min(train_input), max(train_input), 100) line, = ax.plot(x_vals, self.parameters['m'] * x_vals +self.parameters['c'], color='red', label='Regression Line') ax.scatter(train_input, train_output, marker='o', color='green', label='Training Data') # Set y-axis limits to exclude negative values ax.set_ylim(0, max(train_output) + 1) def update(frame): # Forward propagation predictions = self.forward_propagation(train_input) # Cost function cost = self.cost_function(predictions, train_output) # Back propagation derivatives = self.backward_propagation( train_input, train_output, predictions) # Update parameters self.update_parameters(derivatives, learning_rate) # Update the regression line line.set_ydata(self.parameters['m'] * x_vals + self.parameters['c']) # Append loss and print self.loss.append(cost) print("Iteration = {}, Loss = {}".format(frame + 1, cost)) return line, # Create animation ani = FuncAnimation(fig, update, frames=iters, interval=200, blit=True) # Save the animation as a video file (e.g., MP4) ani.save('linear_regression_A.gif', writer='ffmpeg') plt.xlabel('Input') plt.ylabel('Output') plt.title('Linear Regression') plt.legend() plt.show() return self.parameters, self.loss
这个训练的函数代码比较长,我们分三部分来讲解:
(1)初始化随机参数和绘制动画的初始设置
# Initialize random parameters
self.parameters['m'] = np.random.uniform(0, 1) * -1
self.parameters['c'] = np.random.uniform(0, 1) * -1# Initialize loss
self.loss = [] # Initialize figure and axis for animation
fig, ax = plt.subplots()
x_vals = np.linspace(min(train_input), max(train_input), 100)
line, = ax.plot(x_vals, self.parameters['m'] * x_vals +
self.parameters['c'], color='red', label='Regression Line')
ax.scatter(train_input, train_output, marker='o',
color='green', label='Training Data') # Set y-axis limits to exclude negative values
ax.set_ylim(0, max(train_output) + 1)
-
初始化随机参数: m m m 和 c c c 分别是线性回归模型的斜率和截距,使用随机负值初始化
-
初始化损失列表:
self.loss = []
,用于记录每次迭代的损失值。 -
创建动画图像的坐标轴:
- 使用
plt.subplots()
初始化图形。 - 使用
np.linspace
在训练数据范围内生成100个等间距的 x x x 值。 - 用回归线
line
和散点图scatter
绘制初始数据分布和回归线。- 这两个函数不做深入解释了,主要是用动画显示一下结果
- 使用
-
设置 y y y 轴范围:
ax.set_ylim(0, max(train_output) + 1)
,避免负值干扰图形。
(2)定义动画更新逻辑
def update(frame): # Forward propagation predictions = self.forward_propagation(train_input) # Cost function cost = self.cost_function(predictions, train_output) # Back propagation derivatives = self.backward_propagation( train_input, train_output, predictions) # Update parameters self.update_parameters(derivatives, learning_rate) # Update the regression line line.set_ydata(self.parameters['m'] * x_vals + self.parameters['c']) # Append loss and print self.loss.append(cost) print("Iteration = {}, Loss = {}".format(frame + 1, cost)) return line,
-
前向传播:调用
self.forward_propagation(train_input)
计算预测值 -
计算损失:调用
self.cost_function(predictions, train_output)
,基于均方误差(MSE)计算损失 -
反向传播:调用
self.backward_propagation
计算梯度 -
参数更新:使用学习率 α \alpha α 和反向传播计算出来的梯度更新参数
-
更新回归线:根据新的 m m m 和 c c c 重新绘制回归线。
-
记录损失并打印:将当前迭代的损失追加到
self.loss
中,并打印当前迭代信息。
(2)创建动画、保存和显示图像
# Create animation
ani = FuncAnimation(fig, update, frames=iters, interval=200, blit=True) # Save the animation as a video file (e.g., MP4)
ani.save('linear_regression_A.gif', writer='ffmpeg') plt.xlabel('Input')
plt.ylabel('Output')
plt.title('Linear Regression')
plt.legend()
plt.show() return self.parameters, self.loss
-
创建动画:调用
FuncAnimation
动态展示每次迭代后模型的变化,update
函数在FuncAnimation
中由frames=iters
控制,总共被调用iters
次,每帧调用一次,间隔由interval=200
毫秒决定。 -
保存动画:将训练过程保存为 GIF 文件,便于分析。
-
显示图像:绘制最终的回归线和训练数据分布。
-
返回结果:最终返回优化后的参数和记录的损失值。
代码运行结果
#Example usage
linear_reg = LinearRegression()
parameters, loss = linear_reg.train(train_input, train_output, 0.0001, 20)
输出:
Iteration = 1, Loss = 4380.455128289033
Iteration = 1, Loss = 534.7906518669206
Iteration = 1, Loss = 71.34622937840669
Iteration = 1, Loss = 15.49613095399081
Iteration = 2, Loss = 8.765584291635278
Iteration = 3, Loss = 7.9544781683945
Iteration = 4, Loss = 7.856729049602253
Iteration = 5, Loss = 7.844947213272631
Iteration = 6, Loss = 7.843525370234688
Iteration = 7, Loss = 7.843352019334563
Iteration = 8, Loss = 7.8433291255257975
Iteration = 9, Loss = 7.843324363635718
Iteration = 10, Loss = 7.843321787040954
Iteration = 11, Loss = 7.843319473999822
Iteration = 12, Loss = 7.843317192921515
Iteration = 13, Loss = 7.843314915896804
Iteration = 14, Loss = 7.843312639562301
Iteration = 15, Loss = 7.843310363512657
Iteration = 16, Loss = 7.843308087699013
Iteration = 17, Loss = 7.843305812115446
Iteration = 18, Loss = 7.8433035367612325
Iteration = 19, Loss = 7.843301261636267
Iteration = 20, Loss = 7.843298986740505
结果图如下,红色曲线为我们最终的回归曲线:
- 在本地自己运行上述代码,可以看到曲线红色曲线随着梯度下降更新参数的过程。
线性回归线提供了两个变量之间关系的最佳拟合线,捕获因变量 Y Y Y 随自变量 X X X 变化的总体趋势。
3 使用Pytorch实现线性回归
现在已经有许多优秀的机器学习库,如TensorFlow、Scikit-learn等,它们都能帮助我们快速实现线性回归等模型。本文选择PyTorch作为例子,展示如何更简洁地完成建模与训练,同时体验其灵活性与强大的自动微分功能。下面还是基于刚刚编写的代码,我们来看一下做得一些改动:
(1)库引入
import torch
from torch import nn
-
torch
是 PyTorch 的核心库,提供了张量操作和基本数学计算功能,类似于 NumPy 的作用,但支持自动求导和 GPU 加速。 -
torch.nn
是 PyTorch 中构建神经网络的核心模块,提供了实现深度学习模型所需的基本构件。
(2)数据处理
数据要转化为PyTorch的张量形式:
train_input = torch.tensor(data.x[0:500].values, dtype=torch.float32).view(-1, 1)
train_output = torch.tensor(data.y[0:500].values, dtype=torch.float32).view(-1, 1)test_input = torch.tensor(data.x[500:700].values, dtype=torch.float32).view(-1, 1)
test_output = torch.tensor(data.y[500:700].values, dtype=torch.float32).view(-1, 1)
view(-1, 1)
:-1
表示根据剩余维度自动计算大小,1
表示将数据重新组织为一列(每个特征在单独的一列中)。
(3)线性回归类
class LinearRegression(nn.Module):def __init__(self):# 调用 nn.Module 的 __init__ 方法,初始化父类的属性和功能super(LinearRegression, self).__init__()# 定义线性层,输入为1,输出为1self.linear = nn.Linear(1, 1)# 前向传播,等价于前面我们写的forward_propagationdef forward(self, x):return self.linear(x)def train_model(self, train_input, train_output, learning_rate, iters):# 定义损失函数criterion = nn.MSELoss()# 定义优化器optimizer = torch.optim.SGD(self.parameters(), lr=learning_rate)# 初始化损失列表self.loss = []# 初始化图像和动画fig, ax = plt.subplots()x_vals = torch.linspace(train_input.min(), train_input.max(), 100).view(-1, 1)line, = ax.plot(x_vals.numpy(), self.forward(x_vals).detach().numpy(),color='red', label='Regression Line')ax.scatter(train_input.numpy(), train_output.numpy(), marker='o',color='green', label='Training Data')ax.set_ylim(0, train_output.max().item() + 1)def update(frame):# 前向传播predictions = self.forward(train_input)# 计算损失loss = criterion(predictions, train_output)# 反向传播optimizer.zero_grad()loss.backward()# 更新参数optimizer.step()# 更新回归线line.set_ydata(self.forward(x_vals).detach().numpy())# 记录损失self.loss.append(loss.item())print(f"Iteration = {frame + 1}, Loss = {loss.item()}")return line,# 创建动画ani = FuncAnimation(fig, update, frames=iters, interval=200, blit=True)# 保存动画ani.save('linear_regression_pytorch.gif', writer='ffmpeg')# 显示图像plt.xlabel('Input')plt.ylabel('Output')plt.title('Linear Regression')plt.legend()plt.show()return self.linear.weight.data, self.linear.bias.data, self.loss
nn.Module
是 PyTorch 中所有神经网络模型的基类。它为神经网络模型的构建和使用提供了一套通用框架。这里让LinearRegression
类继承这个父类nn.Linear(1, 1)
:定义一个输入维度为1
,输出维度为1
的线性层- 参数存储在
self.linear.weight
和self.linear.bias
中,可以通过model.parameters()
访问
- 参数存储在
改动 | 自己实现 | Pytorch |
---|---|---|
前向传播 | def forward_propagation(self, train_input): m = self.parameters[‘m’] c = self.parameters[‘c’] predictions = np.multiply(m, train_input) + c return predictions | def forward(self, x): return self.linear(x) |
损失函数 | def cost_function(self, predictions, train_output): cost = np.mean((train_output - predictions) ** 2) return cost | criterion = nn.MSELoss() |
反向传播 | def update_parameters(self, derivatives, learning_rate): self.parameters[‘m’] = self.parameters[‘m’] - learning_rate * derivatives[‘dm’] self.parameters[‘c’] = self.parameters[‘c’] - learning_rate * derivatives[‘dc’] | optimizer = torch.optim.SGD(self.parameters(), lr=learning_rate) |
PyTorch张量 vs Numpy | x_vals = torch.linspace(train_input.min(), train_input.max(), 100).view(-1, 1) line, = ax.plot(x_vals.numpy(), self.forward(x_vals).detach().numpy(), color=‘red’, label=‘Regression Line’) ax.scatter(train_input.numpy(), train_output.numpy(), marker=‘o’, color=‘green’, label=‘Training Data’) ax.set_ylim(0, train_output.max().item() + 1) | x_vals = np.linspace(min(train_input), max(train_input), 100) line, = ax.plot(x_vals, self.parameters[‘m’] * x_vals + self.parameters[‘c’], color=‘red’, label=‘Regression Line’) ax.scatter(train_input, train_output, marker=‘o’, color=‘green’, label=‘Training Data’) # Set y-axis limits to exclude negative values ax.set_ylim(0, max(train_output) + 1) |
- 在PyTorch中,上面的
update
中就是用库中定义的前向传播、损失函数和反向传播函数了,就不放在表格中对比了。
最后我们运行一下这段代码:
# 使用示例
linear_reg = LinearRegression()
parameters, bias, loss = linear_reg.train_model(train_input, train_output, 0.0001, 20)
效果是和我们自己实现的差不多的。
- 由于PyTorch包含整个神经网络的功能,所以这里遇到的PyTorch中预定义的不同的优化器和损失函数,在后续学完所有的机器学习方法后再一起介绍,现在仅了解一下就好。
4 扩展:正则化
4.1 正则化解释
在机器学习和回归模型中,正则化是一种通过在目标函数中添加惩罚项来提高模型泛化能力的技术。主要目的是解决以下两个常见问题:
-
过拟合 (Overfitting)
当模型过于复杂,参数过多时,模型可能会记住训练数据中的噪声,从而导致在新数据上的表现变差。- 过拟合的迹象包括训练集上误差很低,但测试集误差很高。
- 正则化通过惩罚大幅度的参数值,限制模型复杂度,从而减少过拟合的风险。
-
多重共线性 (Multicollinearity)
在回归模型中,如果自变量之间高度相关,可能会导致系数的不稳定性。- 正则化可以通过增加惩罚项,使得模型更加鲁棒,从而缓解多重共线性问题。
什么情况下需要正则化
- 数据量少但特征多时,模型容易过拟合。
- 训练误差和测试误差之间的差异很大时,可能存在过拟合问题。
- 存在多重共线性(自变量高度相关)的情况下,系数可能会变得不稳定,需要通过正则化来约束系数。
- 希望对模型进行特征选择时,正则化(如 L 1 L1 L1)可以自动选择重要特征,将无关特征的系数压缩为零。
正则化的主要方法
(1)Lasso 回归 (L1 正则化)
Lasso 回归通过在线性回归目标函数中添加惩罚项来防止过拟合。
应用 Lasso 回归后的目标函数为:
J ( θ ) = 1 2 m ∑ i = 1 m ( y ^ i − y i ) 2 + λ ∑ j = 1 n ∣ θ j ∣ J(\theta) = \frac{1}{2m} \sum_{i=1}^m (\hat{y}_i - y_i)^2 + \lambda \sum_{j=1}^n | \theta_j | J(θ)=2m1i=1∑m(y^i−yi)2+λj=1∑n∣θj∣
- 第一项表示最小二乘误差 (预测值和实际值之间平方差)。
- 第二项是 L 1 L1 L1 正则化项,惩罚回归系数的绝对值之和。
- 优点:Lasso 可以将一些系数缩减为零,从而实现特征选择。
- 缺点:对于特征数大于样本数时,Lasso 的表现可能不稳定。
(2)Ridge 回归 (L2 正则化)
Ridge 回归通过向目标函数添加正则化项来防止过拟合,尤其适用于高多重共线性的数据集。
应用 Ridge 回归后的目标函数为:
J ( θ ) = 1 2 m ∑ i = 1 m ( y ^ i − y i ) 2 + λ ∑ j = 1 n θ j 2 J(\theta) = \frac{1}{2m} \sum_{i=1}^m (\hat{y}_i - y_i)^2 + \lambda \sum_{j=1}^n \theta_j^2 J(θ)=2m1i=1∑m(y^i−yi)2+λj=1∑nθj2
- 第一项表示最小二乘误差。
- 第二项惩罚回归系数平方值之和。
- 优点:Ridge 能够很好地处理多重共线性问题,使模型更加稳定。
- 缺点:Ridge 不能将系数压缩到零,无法进行特征选择。
(3)Elastic Net 回归
Elastic Net 回归结合了 L 1 L1 L1 和 L 2 L2 L2 正则化的优点。
目标函数为:
J ( θ ) = 1 2 m ∑ i = 1 m ( y ^ i − y i ) 2 + α λ ∑ j = 1 n ∣ θ j ∣ + ( 1 − α ) 2 λ ∑ j = 1 n θ j 2 J(\theta) = \frac{1}{2m} \sum_{i=1}^m (\hat{y}_i - y_i)^2 + \alpha \lambda \sum_{j=1}^n |\theta_j| + \frac{(1 - \alpha)}{2} \lambda \sum_{j=1}^n \theta_j^2 J(θ)=2m1i=1∑m(y^i−yi)2+αλj=1∑n∣θj∣+2(1−α)λj=1∑nθj2
- 第一项是最小二乘误差。
- 第二项是 L 1 L1 L1 正则化,第三项是 Ridge 回归。
- λ \lambda λ 控制整体正则化强度。
- α \alpha α 控制 L 1 L1 L1 和 L 2 L2 L2 正则化的混合比例。
- 优点:适用于高维数据和特征数量远大于样本数量的场景,综合了 Lasso 和 Ridge 的优势。
总结
正则化是解决机器学习中过拟合和多重共线性问题的重要方法。在模型复杂或数据稀疏的情况下,正则化不仅能提升模型的泛化能力,还能实现特征选择。根据具体需求,可以选择 Lasso、Ridge 或 Elastic Net。
4.2 正则化实例
我们以一个简单的数据集为例,模拟房价预测:
房屋面积 | 位置评分 | 噪音等级 | 装修评分 | 价格 |
---|---|---|---|---|
1000 | 8 | 4 | 7 | 300,000 |
1200 | 9 | 5 | 6 | 350,000 |
850 | 7 | 3 | 8 | 280,000 |
1300 | 9 | 5 | 7 | 370,000 |
900 | 7 | 4 | 6 | 290,000 |
- 特征:房屋面积、位置评分、噪音等级、装修评分。
- 目标:价格。
正则化前后的对比
(1)正则化之前
- 使用普通的线性回归训练模型。
- 现象:
- 模型可能为每个特征赋予较大的权重。
- 噪音等级(对房价的影响较小)也可能被分配较大的系数,增加模型复杂度。
- 训练集的误差很小,但在测试集上表现差(过拟合)。
特征权重(未正则化) |
---|
房屋面积:100 |
位置评分:50 |
噪音等级:30 |
装修评分:20 |
(2)正则化之后
- 使用 Lasso 正则化 来限制不重要特征的影响。
- 现象:
- 噪音等级的系数被压缩为 0(表示对价格预测影响很小)。
- 保留对价格有显著影响的特征,如房屋面积和位置评分。
- 模型更加简单,泛化能力更强,在测试集上表现更好。
特征权重(Lasso 正则化后) |
---|
房屋面积:90 |
位置评分:40 |
噪音等级:0 |
装修评分:15 |
正则化总结
- 未正则化时:所有特征都会被赋予权重,容易导致模型复杂且过拟合。
- 正则化后:通过缩减或移除不重要的特征,提高模型的简洁性和泛化能力。
5 总结
线性回归广泛应用于金融、经济学、心理学等领域,以理解和预测变量行为。例如,在金融领域,线性回归可用于研究公司股票价格与收益之间的关系,或根据过去的表现预测未来的货币价值。 优点与缺点如下:
优点
- 简单易懂,易于实现,系数具有可解释性。
- 计算效率高,适合处理大数据集,非常适合实时应用。
- 与其他算法相比,对异常值较为鲁棒。
- 常作为更复杂模型的基线模型。
- 历史悠久,广泛应用于各种机器学习库。
缺点
- 假设因变量与自变量之间是线性关系,若该假设不成立,模型表现可能较差。
- 对多重共线性敏感,可能导致系数方差膨胀和预测不稳定。
- 需要对特征进行预处理,确保输入数据适合模型使用。
- 容易发生过拟合或欠拟合。过拟合时,模型学习训练数据过好,无法泛化到新数据;欠拟合时,模型过于简单,无法捕获数据的潜在关系。
- 对于复杂变量关系,解释能力有限。
结论
线性回归是一种基础的机器学习算法,因其简单性、可解释性和高效性而备受推崇。它对于理解变量关系和进行预测非常有用。然而,其线性假设和对多重共线性的敏感性在使用时需要注意。如果这些限制条件被充分考虑,线性回归可以成为数据分析和预测的强大工具。
相关文章:
机器学习详解(3):线性回归之代码详解
文章目录 1 数据预处理2 构建线性回归模型并绘制回归线初始化方法前向传播:forward_propagation代价函数:cost_function反向传播:backward_propagation参数更新:update_parameters训练方法:train代码运行结果 3 使用Py…...
工业检测基础-工业相机选型及应用场景
以下是一些常见的工业检测相机种类、检测原理、应用场景及选型依据: 2D相机 检测原理:基于二维图像捕获,通过分析图像的明暗、纹理、颜色等信息来检测物体的特征和缺陷.应用场景:广泛应用于平面工件的外观检测,如检测…...
标准状态下一个气体分子每秒平均碰撞次数的估算
要估算在标准状态(0C, 1个大气压)下,一个气体分子在1秒内与其他分子的碰撞次数,我们可以使用一些基本的物理和化学原理。这个过程涉及到气体动力学理论,特别是麦克斯韦-玻尔兹曼分布。 计算气体分子的平均速率…...
使用PHPUnit使用本地调试代替远程调试,快速提高开发效率
Laravel 是一个在 Linux 环境下表现非常出色的 PHP 框架,但它在 Windows 环境下可能会遇到一些兼容性和配置问题。为了调试或没试的方便可以在 Windows 环境下进行 Laravel PHPUnit进行本地调试和测试。 本地主要针对断点调试效果非常高效。 在 Laravel 中&#x…...
Android 镜像模式和扩展模式区别探讨-Android14
Android 镜像模式和扩展模式区别探讨 1、区分镜像模式和扩展模式1.1 扩展屏是否有显示内容1.2 镜像模式显示条件 2、镜像模式界面 同屏显示和异屏显示探讨DisplayManagerService启动及主屏添加-Android13 Android主副屏显示-Android14 1、区分镜像模式和扩展模式 LogicalDispla…...
链表头文件大更新!!!
引言 原文章:链表简介及自制链表操作头文件_自己写一个链表头文件-CSDN博客。 此次更新添加了更多功能,让改头文件更 人性化 。 安装教程见原文章。 介绍 linked_list.h 头文件 linked_list.h 是一个 C 头文件,定义了一个模板类 LinkedListÿ…...
ROS2创建 base 包用于其他模块的参数配置和头文件依赖
Demo 背景 ROS2项目开发中存在以下需求:有多个包需要读取一些共同的配置项(以txt或者yaml形式存在),且依赖于一些公用的utils工具代码(C)。Solution: 创建一个 base_config 包来“存放” 配置文件和公用的头文件。gitee address: Gitee/CDal…...
设计模式の软件设计原则
文章目录 前言一、聚合&组合&继承&依赖1.1、继承1.2、组合1.3、聚合1.4、依赖 二、单一职责原则2.1、单一职责原则反面案例2.2、单一职责原则反面案例的改进 三、接口隔离原则3.1、接口隔离原则反面案例3.2、接口隔离原则反面案例的改进 四、依赖倒转原则4.1、依赖…...
【python自动化四】日志打印
我们在进行自动化测试时,需要打印过程日志和结果日志等,这里记录下日志的相关配置。这里我们直接自己新建一个logger。 先贴上日志代码如下,可根据需要修改: import logging import os import timefrom logging.handlers import …...
E498 ThinkPHP+MYSQL+LW+纯洁婚纱网站系统的设计与实现 源码 配置 文档 全套资料
婚纱网站系统的设计与实现 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 在互联网和电子商务迅速发展的今天,网络已经是人们日常生活所不可缺少的信息获取渠道,人们日常生活基本已完全被网络所覆盖,互联网影响到各…...
【PostgreSQL系列】列类型从整数转换为 UUID
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
shell脚本实战案例
文章目录 实战第一坑功能说明脚本实现 实战第一坑 实战第一坑:在Windows系统写了一个脚本,比如上面,随后上传到服务,执行会报错 原因: 解决方案:在linux系统touch文件,并通过vim添加内容&…...
VAE为什么叫变分(variational),相对于AE有什么区别。
VAE为什么叫变分(variational),相对于AE有什么区别。 VAE为什么叫变分(variational)?VAE相对于AE有什么区别? VAE为什么叫变分(variational)? 变分自编码器&…...
Codeforces Round 991 (Div. 3)
补题连接 A. Line Breaks 思路:从头开始累加单词个数,超过m就退出。 代码: #include <bits/stdc.h> using namespace std; #define int long longvoid solve() {int n, m, k;cin >> n >> m;vector<string> a(n);…...
红日靶场vulnstark 4靶机的测试报告[细节](一)
目录 一、测试环境 1、系统环境 2、注意事项 3、使用工具/软件 二、测试目的 三、操作过程 1、信息搜集 2、漏洞利用Getshell ①Struts 2 s2-045漏洞 手工利用s2-45漏洞 Msf综合利用 ②Tomcat框架(CVE-2017-12615) ③phpMyAdmin(CVE-2018-12613) 构造语句写入冰蝎木…...
Android上运行OpenCV(Android Studio)
用Android Studio的话,整体来说没什么难的,照着教程来做就好了。 【OpenCV】OpenCV库的安装 - Android与OpenCV系列教程_哔哩哔哩_bilibili 主要就是导入module,然后加入依赖。代码只有几行。 if(OpenCVLoader.initLocal()){Toast.makeText(…...
代码随想录算法训练营day50|动态规划12
不同的子序列 给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。、 编辑距离中的删除元素,其实就是直接变数字,其只删除原来的较长的数组里的元素 递推模拟,使用s的最后一个元素匹配,或者删除…...
图像生成-扩散模型的经典之作DDPM
论文:https://arxiv.org/pdf/2006.11239 项目:https://github.com/hojonathanho/diffusion Denoising Diffusion Probabilistic Models (DDPM) 是一种生成模型,它通过一系列逐步添加噪声的过程将数据点映射到一个简单的先验分布(…...
知识拓展 ?. 连选链操作
?. 连选链操作 ?. 可选链操作符 ?. 是可选链操作符,常用于访问引用类型具有不确定性的内部数据时,比如要访问一个对象中的数组,不确定数组一定有数据就可以使用 ? 取读取它的 length 属性,如果对象没有这个属性也仅会返回 …...
API设计指南:详解HTTP状态码错误解析、HTTP方法及参数命名规则
目录 1、HTTP API规范1.1 原则1.2 协议1.3 版本1.4 路径1.5 HTTP 方法(Method)1.6 过滤信息1.7 参数命名1.8 HTTP 状态码(Response Code)1.9 鉴权 2、状态码2.1 API返回基础规范2.2 常见的 HTTP 状态码2.3 API错误信息应该放到响应…...
【D3.js in Action 3 精译_043】5.1 饼图和环形图的创建(三):圆弧的绘制
当前内容所在位置: 第五章 饼图布局与堆叠布局 ✔️ 5.1 饼图和环形图的创建 ✔️ 5.1.1 准备阶段(一)5.1.2 饼图布局生成器(二)5.1.3 圆弧的绘制(三) ✔️5.1.4 数据标签的添加(四&…...
7. 一分钟读懂“单例模式”
7.1 模式介绍 单例模式就像公司里的 打印机队列管理系统,无论有多少员工提交打印任务,大家的请求都汇总到唯一的打印管理中心,按顺序排队输出。这个中心必须全局唯一,避免多个队列出现资源冲突,保证打印任务井然有序。…...
如何让谷歌外链看起来更真实?
在SEO优化过程中,外链的自然性往往会被忽视,尤其是在一些急于见效的策略中,外链往往集中在高权重的少数几个网站上,导致外链结构单一且缺乏多样性。这样的外链网络容易让搜索引擎怀疑其真实性,进而影响网站排名。如何才…...
C标签和 EL表达式的在前端界面的应用
目录 前言 常用的c标签有: for循环 1 表示 普通的for循环的 2 常在集合中使用 表示 选择关系 1 简单的表示如果 2 表示如果。。否则。。 EL表达式 格式 : ${属性名/对象/ 集合} 前言 本篇博客介绍 c标签和el表达式的使用 使用C标签 要引入 …...
Luma 视频生成 API 对接说明
Luma 视频生成 API 对接说明 随着 AI 的应用变广,各类 AI 程序已逐渐普及。AI 已逐渐深入到人们的工作生活方方面面。而 AI 涉及的行业也越来越多,从最初的写作,到医疗教育,再到现在的视频。 Luma 是一个专业高质量的视频生成平…...
嵌入式基础:Linux C语言:Day7
重点: strlen()函数\strcpy()函数\strcat实现\strcmp()实现 数组的清空:bzero函数、memset函数 一、字符数组 <1> 概念 字符数组本质上就是一个数组,保存一个个字符,也一般用来保存字符串 字符串由多个字符组成的一个字符…...
阿里云盘permission denied
问题是执行 ./aliyunpan 时遇到了 Permission denied 的错误。这通常是因为文件没有执行权限。以下是解决问题的步骤: 检查文件权限 运行以下命令检查文件的权限: ls -l aliyunpan输出中会看到类似以下内容: -rw-r--r-- 1 user group 123…...
Flink学习连载文章12--FlinkSQL高级部分
eventTime 测试数据如下: {"username":"zs","price":20,"event_time":"2023-07-17 10:10:10"} {"username":"zs","price":15,"event_time":"2023-07-17 10:10:3…...
缓冲区溢出基础与实践
缓冲区溢出 缓冲区溢出是指当计算机向缓冲区内填充数据时超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上。理想的情况是:程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间相匹…...
matlab figure函数 single 数据类型
1.matlab figure函数详细介绍 在MATLAB中,figure函数用于创建新的图形窗口或激活现有的图形窗口。以下是figure函数的详细介绍和用法: 基本用法 创建新图形窗口:不带任何参数调用figure会创建一个新的图形窗口,并将其设为当前活…...
量化交易系统开发-实时行情自动化交易-8.15.Ptrade/恒生平台
19年创业做过一年的量化交易但没有成功,作为交易系统的开发人员积累了一些经验,最近想重新研究交易系统,一边整理一边写出来一些思考供大家参考,也希望跟做量化的朋友有更多的交流和合作。 接下来会对于Ptrade/恒生平台介绍。 P…...
Vue03
目录 一、今日目标 1.生命周期 2.综合案例-小黑记账清单 3.工程化开发入门 4.综合案例-小兔仙首页 二、Vue生命周期 三、Vue生命周期钩子 四、生命周期钩子小案例 1.在created中发送数据 六、工程化开发模式和脚手架 1.开发Vue的两种方式 2.Vue CLI脚手架 基本介绍…...
【AI学习】Mamba学习(十九):关于S4-FouT
在前面《Mamba学习(十六):从S4到S5模型》一文中,提到了S4D-Lin,其具体状态矩阵A的初始化形式为: S4D-Lin对比S4D-Inv是一种更简单的形式,可以看作是对S4-FouT(S4的另外一种变体&am…...
YOLOv5-C3模块实现
YOLOv5-C3模块实现 🍨 本文为🔗365天深度学习训练营 中的学习记录博客 🍖 原作者:K同学啊 电脑系统:Windows11 显卡型号:NVIDIA Quadro P620 语言环境:python 3.9.7 编译器:jupyt…...
ubuntu下Qt5自动编译配置QtMqtt环境(10)
文章目录 [toc]1、概述2、下载QtMqtt源码3、编译4、验证5、参考6、视频 更多精彩内容👉内容导航 👈👉Qt网络编程 👈 1、概述 Qt默认是不包含mqtt库的,如果需要使用到mqtt库就只能自己编译配置; 网络所有的…...
切比雪夫不等式:方差约束下的概率估计
切比雪夫不等式:方差约束下的概率估计 背景 在概率分析中,切比雪夫不等式是一个常用的工具,它通过引入随机变量的 方差信息,给出了偏离均值的概率界限。这一不等式是对 马尔科夫不等式 的自然扩展,结合了更丰富的分布…...
SIP系列七:ICE框架(P2P通话)
我的音视频/流媒体开源项目(github) SIP系列目录 目录 一、NAT 1、NAT介绍 2、NAT类型 2.1、 完全圆锥型NAT 2.2、受限圆锥型NAT 2.3、端口受限圆锥型NAT 2.4、对称NAT 3、NAT打洞 3.1、不同一NAT下 3.2、同一NAT下 二、ICE 三、ICE中的SDP 至此&#x…...
小程序-基于java+SpringBoot+Vue的智慧校园管理系统设计与实现
项目运行 1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.硬件环境:…...
Visual Studio 2022创建离线安装包
步骤1: 下载 Visual Studio 引导程序(最新版) 历史版本 步骤2 新建文件夹“E:\VS2022”,将下载的“vs_Professional.exe”拷贝到文件夹下在此文件夹窗口按住shift鼠标右键,选择“在此处打开powershell窗口” 步骤3 根据需要将代码复制到…...
Android 实现中英文切换
在开发海外项目的时候,需要实现app内部的中英文切换功能,所有的英文都是内置的,整体思路为: 创建一个sp对象,存储当前系统的语言类型,然后在BaseActivity中对语言进行判断; //公共Activitypubl…...
CmakeLists学习刨根问底
必要的两项内容 cmake_minimum_required(VERSION 2.5)project(mymuduo) 这行代码指定了构建项目所需的CMake最低版本为2.5。CMake是一个跨平台的自动化构建系统,它使用CMakeLists.txt文件来定义项目的构建过程。定义项目的名称为mymuduo。CMake将使用这个名称来生成…...
策略模式实战 - 猜拳游戏
**可以整体的替换一套算法,这就是策略模式。**这样对于同一个问题,可以有多种解决方案——算法实现的时候,可以通过策略模式来非常方便的进行算法的整体替换,而各种算法是独立封装好的,不用修改其内部逻辑。 具体的实…...
VoCo-LLaMA: Towards Vision Compression with Large Language Models
视觉语言模型在各种多模态任务上取得了显著的成功,但经常受到有限上下文窗口和处理高分辨率图像输入和视频的高计算成本的瓶颈。视觉压缩可以通过减少视觉令牌数量避免该问题。先前方法使用额外模块压缩视觉令牌并强制LLM理解压缩的令牌。然而,LLM对视觉…...
每日小知识
Kafka是一个分布式流平台,具有高性能、高可靠性和可扩展性的特点。它主要用于处理实时的数据流,将数据以高吞吐量的方式进行发布和订阅。以下是关于Kafka的几个基本概念和优势的介绍: 概念: 生产者(Producer…...
Linux其二设置端口号,静态ip以及命令
目录 1、VI编辑器 【linux版本的文本文件】 2) 补充的vi编辑器的其他内容(了解) 2、ln 连接的意思 link的缩写 3、文件的查看 【重点】 4、压缩与解压(重点) 5、find 查找命令 6、which & whereis 作用是一样的,表示某…...
吉林大学23级数据结构上机实验(第7周)
A 去火车站 寒假到了,小明准备坐火车回老家,现在他从学校出发去火车站,CC市去火车站有两种方式:轻轨和公交车。小明为了省钱,准备主要以乘坐公交为主。CC市还有一项优惠政策,持学生证可以免费乘坐一站轻轨&…...
SpringBoot(整合MyBatis + MyBatis-Plus + MyBatisX插件使用)
文章目录 1.整合MyBatis 1.需求分析2.数据库表设计3.数据库环境配置 1.新建maven项目2.pom.xml 引入依赖3.application.yml 配置数据源4.Application.java 编写启动类5.测试6.配置类切换druid数据源7.测试数据源是否成功切换 4.Mybatis基础配置 1.编写映射表的bean2.MonsterMap…...
【2024最新】基于Springboot+Vue的网上图书商城平台Lw+PPT
作者:计算机搬砖家 开发技术:SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等,“文末源码”。 专栏推荐:SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:Java精选实战项…...
JAVA-面向对象基础
文章目录 概要封装多态抽象类接口内部类为什么需要内部类 概要 面向对象是一种编程范式或设计哲学,它将软件系统设计为由多个对象组成,这些对象通过特定的方式相互作用 封装 将数据和操作数据的方法封装在一个类中,并通过访问修饰符控制对…...
Y3编辑器官方文档1:编辑器简介及菜单栏详解(文件、编辑、窗口、细节、调试)
文章目录 一、新建项目二、 编辑器主界面2.1 游戏场景2.2 导航栏/菜单栏2.3 功能栏三、菜单栏详细介绍3.1 文件3.1.1 版本管理3.1.2 项目管理(多关卡)3.1.2.1 多关卡功能说明3.1.2.2 关卡切换与关卡存档3.2 编辑3.2.1 通用设置3.2.2 键位设置3.3 窗口(日志)3.4 细节3.4.1 语言…...