线性回归是统计学中用来预测连续数值的一种方法,它通过建立一个或多个自变量(解释变量)与因变量(响应变量)之间的关系模型来进行预测。线性回归可以分为确定性关系和不确定性关系两大类。确定性关系可以通过函数表达,并且通常被称为相关性,可以通过回归分析来研究。
线性回归模型通常可以表示为:
y = w * x + b
其中,y是因变量,x是自变量,w是权重,b是偏置项。线性回归包括标准线性回归、局部加权线性回归、岭回归、Lasso回归和逐步线性回归等类型。
标准线性回归的参数可以通过梯度下降法或正则表达式求解。由于梯度下降法已经在之前的文章中介绍过,本文将介绍使用正则表达式求解的方法。首先,计算损失函数的导数:
dL/dw = 2 * (wx - y)
然后,令导数等于0,可以得到:
w = (X^T * X)^(-1) * X^T * Y
其中,X是训练数据,Y是对应的标签。以下是标准线性回归的Python代码实现:
def standardLinearRegression(self, x, y):
if self.norm_type == "Standardization":
x = preProcess.Standardization(x)
else:
x = preProcess.Normalization(x)
xTx = np.dot(x.T, x)
if np.linalg.det(xTx) == 0:
print("Error: Singular Matrix!")
return
w = np.dot(np.linalg.inv(xTx), np.dot(x.T, y))
return w
局部加权线性回归通过为预测点周围的点分配权重来解决线性回归中的欠拟合问题。然后,对这些点应用常规的回归分析。局部加权线性回归的损失函数为:
L = sum((y_i - (w * x_i + b))^2 * w_i)
其中,w_i是权重。权重的计算类似于SVM中的核函数,由下式给出:
w_i = exp(-||x_i - x)||^2 / (2 * k^2)
以下是局部加权线性回归的Python代码实现:
def LWLinearRegression(self, x, y, sample):
if self.norm_type == "Standardization":
x = preProcess.Standardization(x)
else:
x = preProcess.Normalization(x)
sample_num = len(x)
weights = np.eye(sample_num)
for i in range(sample_num):
diff = sample - x[i, :]
weights[i, i] = np.exp(np.dot(diff, diff.T) / (-2 * self.k ** 2))
xTx = np.dot(x.T, np.dot(weights, x))
if np.linalg.det(xTx) == 0:
print("Error: Singular Matrix!")
return
result = np.dot(np.linalg.inv(xTx), np.dot(x.T, np.dot(weights, y)))
return np.dot(sample.T, result)
当特征维度大于样本数量时,输入矩阵不是满秩的,其逆矩阵不存在。为了解决这个问题,岭回归通过添加L2正则化项来使矩阵非奇异。岭回归的损失函数为:
L = sum((y_i - (w * x_i + b))^2) + lambda * sum(w_i^2)
以下是岭回归的Python代码实现:
def ridgeRegression(self, x, y):
if self.norm_type == "Standardization":
x = preProcess.Standardization(x)
else:
x = preProcess.Normalization(x)
feature_dim = len(x[0])
xTx = np.dot(x.T, x)
matrix = xTx + np.exp(feature_dim) * self.lamda
if np.linalg.det(xTx) == 0:
print("Error: Singular Matrix!")
return
w = np.dot(np.linalg.inv(matrix), np.dot(x.T, y))
return w
Lasso回归与岭回归类似,它在损失函数中添加了L1正则化项:
L = sum((y_i - (w * x_i + b))^2) + lambda * sum(abs(w_i))
由于L1正则化包含绝对值表达式,损失函数在任何地方都不可导。因此,应用坐标下降法(CD)。坐标下降法在每次迭代中沿着一个方向得到最小值。以下是Lasso回归的Python代码实现:
def lassoRegression(self, x, y):
if self.norm_type == "Standardization":
x = preProcess.Standardization(x)
else:
x = preProcess.Normalization(x)
y = np.expand_dims(y, axis=1)
sample_num, feature_dim = np.shape(x)
w = np.ones([feature_dim, 1])
for i in range(self.iterations):
for j in range(feature_dim):
h = np.dot(x[:, 0:j], w[0:j]) + np.dot(x[:, j+1:], w[j+1:])
w[j] = np.dot(x[:, j], (y - h))
if j == 0:
w[j] = 0
else:
w[j] = self.softThreshold(w[j])
return w
逐步线性回归与Lasso回归类似,它在每次迭代中应用贪心算法来得到最小值,而不是坐标下降法。逐步线性回归在每次迭代中增加或减少权重的一小部分。以下是逐步线性回归的Python代码实现:
def forwardstepRegression(self, x, y):
if self.norm_type == "Standardization":
x = preProcess.Standardization(x)
else:
x = preProcess.Normalization(x)
sample_num, feature_dim = np.shape(x)
w = np.zeros([self.iterations, feature_dim])
best_w = np.zeros([feature_dim, 1])
for i in range(self.iterations):
min_error = np.inf
for j in range(feature_dim):
for sign in [-1, 1]:
temp_w = best_w
temp_w[j] += sign * self.learning_rate
y_hat = np.dot(x, temp_w)
error = ((y - y_hat) ** 2).sum()
if error < min_error:
min_error = error
best_w = temp_w
w = best_w
return w
线性回归有多种方法来求解最优参数。本文仅介绍了一些基本算法。最后,让将线性回归与Sklearn中的线性回归进行比较,检测性能如下所示:
Sklearn线性回归性能: