线性回归
X和Y之间的关系,数据X就是特征,目标Y就是标签,X的系数就是参数,参数决定X对Y的影响程度(重要程度):
回归就是确定一个维度(一条线、平面)来最好的拟合数据点,使得X对Y的解释力度最好,误差最小,R-squared最大。
假设拟合的平面(决策方程)是:
微调是,使得结果更精准;核心影响是
数据处理时添加一列向量,目的将偏置项放入矩阵计算。
求解出参数后利用真实的特征求解得到的是预测值,而实际生产环境中的真实值
和预测值(即真实值在平面上的投影点)之间肯定存在差异,即线性回归解释的变量(现实中存在的样本)是存在线性关系的。然而这种关系并不是严格的函数映射关系,但是构建的模型(方程)却是严格的函数映射关系的,因此对于每个样本来说,我们拟合的结果会与真实值之间存在一定的误差,该差异定义成误差项
,于是真实值和特征之间的关系表达:
对于误差项越小越好接近于0,定义一个函数Loss函数区拟合数据,使得模型的误差项或Loss最小。
误差项:一般要求iid且
~Gauss(0,
),即
代入后得到
确定x和α的组合所得到的预测值和真实值y之间误差最小,成为y的可能性越大越好。
iid:输入空间X中的所有样本服从一个隐含未知的分布,训练数据的所有样本都是独立地从这个分布上采样而得。机器学习是利用当前获取到的信息(或数据)进行训练学习,用以对未来的数据进行预测、模拟。所以都是建立在历史数据之上,采用模型去拟合未来的数据。因此需要使用的历史数据具有总体的代表性。要从已有的数据(经验) 中总结出规律来对未知数据做决策,如果获取训练数据是不具有总体代表性的,就是特例的情况,那规律就会总结得不好或是错误,因为这些规律是由个例推算的,不具有推广的效果。因此通过独立同分布的假设,就可以大大减小训练样本中个例的情形。
在自然界与生产中,一些现象受到许多相互独立的随机因素的影响,如果每个因素所产生的影响都很微小时,总的影响可以看作是服从正态分布的,Gauss分布说明了误差影响(浮动)不会很大,极小情况下影响会比较大,但这也属于正常情况,中心极限定理证明在适当的条件下,大量相互独立随机变量的均值经适当标准化后依分布收敛于正态分布。
引入概率论中最大似然函数:什么样的参数跟数据组合后恰好是真实值,由于最大似然函数之间是相乘(iid时联合概率密度等于边缘概率密度乘积),所以引入对数似然函数:
目标函数为(预测值和真实值之间误差越小越好,J(α)即上式中非常数部分):
上式对α求偏导得到:
令其为0得到
评估方法一般有
1、评估项R-squared(决定系数,越接近于1表明模型拟合效果越好):
衡量模型对数据方差的解释能力。值的范围通常是 0 到 1,越接近 1 表示模型拟合越好。值为负数时,表明模型的预测效果比简单的均值模型还差。
2、MAE(Mean Absolute Error,平均绝对误差)
MAE 是实际值与预测值的绝对误差的平均值。它不会对大的误差产生过大的惩罚,适合对每个误差的“公平”处理。
3、MSE(Mean Squared Error,均方误差)
MSE 是实际值与预测值的平方误差的平均值。由于平方的作用,较大的误差会被放大,因此对离群值更加敏感。
4、RMSE(Root Mean Squared Error,均方根误差)
RMSE 是 MSE 的平方根,具有与原始数据相同的单位,通常用于对误差的直观解释。它对大误差特别敏感。
5、MAPE(Mean Absolute Percentage Error,平均绝对百分比误差)
MAPE 衡量的是预测误差相对于实际值的百分比。适用于预测任务,特别是对误差比例敏感的情况。但当实际值接近零时,MAPE 会变得不稳定。
6、RMSLE(Root Mean Squared Logarithmic Error,均方根对数误差)
RMSLE 用于预测时,特别是对目标变量值有较大差异(如指数增长)时。它通过对数变换使得模型对大值和小值的误差更加均衡。
7、Adjusted R²(调整后的 R²)
其中,n 是样本量,p 是特征数量。调整后的 R² 通过惩罚模型中过多的特征,避免模型对过多特征的过拟合,适用于多变量回归分析。
8、Huber Loss
Huber Loss 是 MSE 和 MAE 的结合。对于小误差,它类似 MSE;对于大误差,它转化为 MAE,从而减少离群值的影响。
9、Explained Variance Score
解释方差得分衡量模型的预测结果与实际结果之间方差的比例,值越接近 1,模型越能解释数据的变异性。
10、Confusion Matrix (适用于分类任务)
用于分类问题,是一个用于评估分类模型性能的工具,尤其适用于二分类问题。它呈现了模型预测结果与实际标签之间的关系。混淆矩阵显示了四个基本值:
- True Positive (TP):实际为正类且预测为正类的样本数。
- True Negative (TN):实际为负类且预测为负类的样本数。
- False Positive (FP):实际为负类但预测为正类的样本数(假阳性)。
- False Negative (FN):实际为正类但预测为负类的样本数(假阴性)。
11、Precision、Recall、F1-Score(适用于分类任务)
Precision(精确率):正确预测为正例的样本占预测为正例的比例,衡量模型预测为正类的样本中,实际为正类的比例。它反映了模型预测正类的准确性。精确率高意味着模型在预测为正类时,错误预测的概率较小,假阳性较少。
Recall(召回率):正确预测为正例的样本占实际正例的比例,衡量实际为正类的样本中,被模型正确预测为正类的比例。它反映了模型捕捉到正类样本的能力。召回率高意味着模型能够较好地捕捉到所有的正类样本,假阴性较少。但如果召回率非常高,可能会牺牲精确率,导致假阳性增多。
F1-Score:是精确率和召回率的调和平均值,是两者的平衡指标。当精确率和召回率的权重相似时,F1-Score 是非常有用的评估标准。它可以综合考虑模型的精度和召回能力。F1-Score 越高,表明模型在精确率和召回率之间达到了较好的平衡。它通常用于处理类不平衡问题,因为它在考虑两者的同时,能够避免单一指标过高或过低的问题。
-
Precision 和 Recall 是相互竞争的指标。通常,当精确率提高时,召回率会下降,反之亦然。选择精确率还是召回率取决于任务的具体要求:
- 如果假阳性(误将负类预测为正类)代价较高,可以优先考虑 精确率。
- 如果假阴性(误将正类预测为负类)代价较高,可以优先考虑 召回率。
12、ROC Curve (Receiver Operating Characteristic Curve)
ROC 曲线是评估二分类模型性能的常用工具,特别是在处理类不平衡问题时。它绘制了不同的 True Positive Rate (TPR)(召回率)和 False Positive Rate (FPR)(假阳性率)之间的关系。它有助于可视化模型在不同阈值下的表现。
- 横轴为 FPR(假阳性率),纵轴为 TPR(召回率)。
- ROC 曲线展示了在不同阈值下,模型如何平衡假阳性和真阳性的比率。曲线下的面积(AUC)通常用来衡量分类器的性能,AUC越接近 1,模型越好。
- 完美模型的 ROC 曲线会接近左上角(即 FPR=0, TPR=1)。
- 随机猜测的模型的 ROC 曲线接近对角线(即 FPR = TPR)。
梯度下降(优化算法常用)eg:
寻找目标函数(损失函数)的终点(极值点),什么样的参数和数据的组合以什么样的方向使得目标函数最快达到极值点,因为是寻找极小值点,要求Loss最小,所以是梯度的反方向,其次参数更新速度要求要慢,需要沿着梯度的方向寻找极小值点。
批量梯度下降,上式求偏导得到:
当前参数为随机值θj,所以下一次更新的参数为:
容易得到最优解,但是每次考虑所有样本速度慢
随机梯度下降,每次寻找一个样本,迭代速度快但是不一定朝着收敛方向:
小批量梯度下降法,每次选择更新一小部分数据:
LR学习率(步长):对结果会产生巨大影响,上式中α即LR,一般初始为0.01,无法容忍的小,批处理batch数量一般选择32,64或128:
梯度下降该监督算法的优化目标为:
其中m是样本数,首先从utils.features导入prepare_for_training模块,处理数据标准化流程和特征变换。
# linear_regression.py
import numpy as np
from utils.features import prepare_for_training
class LinearRegression:
def __init__(self,data,labels,polynomial_degree = 0,sinusoid_degree = 0,normalize_data=True):
"""
Standardize data preprocessing operations
Obtain the number of all features
Initialize parameter matrix
"""
(data_processed, features_mean, features_deviation) = prepare_for_training(data, polynomial_degree, sinusoid_degree,normalize_data=True)
self.data = data_processed
self.labels = labels
self.features_mean = features_mean
self.features_deviation = features_deviation
self.polynomial_degree = polynomial_degree
self.sinusoid_degree = sinusoid_degree
self.normalize_data = normalize_data
num_features = self.data.shape[1] # num of features/variables
self.theta = np.zeros((num_features,1)) # bias term
def train(self,alpha,num_iterations = 500):
"""
Main function, gradient descent algorithm
par: learn rate, num_iteration
"""
cost_history = self.gradient_descent(alpha,num_iterations)
return self.theta,cost_history
def gradient_descent(self,alpha,num_iterations):
"""
actual iteration module will iterate num_iterations times
"""
cost_history = []
for _ in range(num_iterations):
self.gradient_step(alpha) # Implement parameter updates every iteration
cost_history.append(self.cost_function(self.data,self.labels))
return cost_history
def gradient_step(self,alpha):
"""
Parameter update module
"""
num_examples = self.data.shape[0]
prediction = LinearRegression.hypothesis(self.data,self.theta)
delta = prediction - self.labels
theta = self.theta
theta = theta - alpha*(1/num_examples)*(np.dot(delta.T,self.data)).T
self.theta = theta
def cost_function(self,data,labels):
"""
Loss function calculation module: J(theta)
It can also be MAE or MSE
"""
num_examples = data.shape[0]
delta = LinearRegression.hypothesis(self.data,self.theta) - labels
cost = (1/2)*np.dot(delta.T,delta)/num_examples
return cost[0][0]
@staticmethod
def hypothesis(data,theta):
predictions = np.dot(data,theta)
return predictions
def get_cost(self,data,labels):
data_processed = prepare_for_training(data, self.polynomial_degree, self.sinusoid_degree, self.normalize_data)[0]
return self.cost_function(data_processed,labels)
def predict(self,data):
"""
Use the trained parameter model to predict the regression value results
"""
data_processed = prepare_for_training(data, self.polynomial_degree, self.sinusoid_degree, self.normalize_data)[0]
predictions = LinearRegression.hypothesis(data_processed,self.theta)
return predictions
# MultivariateRegression.py
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import load_diabetes # https://archive.ics.uci.edu
from sklearn.model_selection import train_test_split
from linear_regression import LinearRegression
diabetes = load_diabetes()
data = pd.DataFrame(diabetes.data, columns=diabetes.feature_names)
data['target'] = diabetes.target
X_train, X_test, y_train, y_test = train_test_split(data.iloc[:,:len(diabetes.feature_names)], data.iloc[:,len(diabetes.feature_names):], train_size= 0.2, test_size=0.2, random_state=42)
# sns.pairplot(X_train+y_train, hue='target', palette='viridis')
# plt.show()
num_iterations = 500
learning_rate = 0.01
linear_regression = LinearRegression(X_train, y_train, polynomial_degree = 0, sinusoid_degree = 0)
(theta, cost_history) = linear_regression.train(learning_rate, num_iterations)
print(f"start loss: {cost_history[0]}")
print(f"end loss: {cost_history[-1]}")
plt.plot(range(num_iterations), cost_history)
plt.xlabel('Iterations')
plt.ylabel('Cost')
plt.title('Gradient Descent Progress')
plt.show()
y_predictions = linear_regression.predict((X_test))
print(f"{np.hstack((y_predictions,y_test))}")
# BivariateRegression.py
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import plotly
import plotly.graph_objs as go
from sklearn.datasets import load_diabetes
plotly.offline.init_notebook_mode()
from linear_regression import LinearRegression
diabetes = load_diabetes()
data = pd.DataFrame(diabetes.data, columns=diabetes.feature_names)
data['target'] = (diabetes.target-np.mean(diabetes.target))/np.std(diabetes.target)
data =data[['age','bmi','target']]
train_data = data.sample(frac=0.8)
test_data = data.drop(train_data.index)
input_param_name_1 = 'age'
input_param_name_2 = 'bmi'
output_param_name = 'target'
x_train = train_data[[input_param_name_1, input_param_name_2]].values
y_train = train_data[[output_param_name]].values
x_test = test_data[[input_param_name_1, input_param_name_2]].values
y_test = test_data[[output_param_name]].values
# Configure the plot with training dataset.
plot_training_trace = go.Scatter3d(
x=x_train[:, 0].flatten(),
y=x_train[:, 1].flatten(),
z=y_train.flatten(),
name='Training Set',
mode='markers',
marker={
'size': 10,
'opacity': 1,
'line': {
'color': 'rgb(255, 255, 255)',
'width': 1
},
}
)
plot_test_trace = go.Scatter3d(
x=x_test[:, 0].flatten(),
y=x_test[:, 1].flatten(),
z=y_test.flatten(),
name='Test Set',
mode='markers',
marker={
'size': 10,
'opacity': 1,
'line': {
'color': 'rgb(255, 255, 255)',
'width': 1
},
}
)
plot_layout = go.Layout(
title='Date Sets',
scene={
'xaxis': {'title': input_param_name_1},
'yaxis': {'title': input_param_name_2},
'zaxis': {'title': output_param_name}
},
margin={'l': 0, 'r': 0, 'b': 0, 't': 0}
)
plot_data = [plot_training_trace, plot_test_trace]
plot_figure = go.Figure(data=plot_data, layout=plot_layout)
plotly.offline.plot(plot_figure)
num_iterations = 500
learning_rate = 0.01
polynomial_degree = 0
sinusoid_degree = 0
linear_regression = LinearRegression(x_train, y_train, polynomial_degree, sinusoid_degree)
(theta, cost_history) = linear_regression.train(
learning_rate,
num_iterations
)
print('开始损失',cost_history[0])
print('结束损失',cost_history[-1])
plt.plot(range(num_iterations), cost_history)
plt.xlabel('Iterations')
plt.ylabel('Cost')
plt.title('Gradient Descent Progress')
plt.show()
predictions_num = 10
x_min = x_train[:, 0].min()
x_max = x_train[:, 0].max()
y_min = x_train[:, 1].min()
y_max = x_train[:, 1].max()
x_axis = np.linspace(x_min, x_max, predictions_num)
y_axis = np.linspace(y_min, y_max, predictions_num)
x_predictions = np.zeros((predictions_num * predictions_num, 1))
y_predictions = np.zeros((predictions_num * predictions_num, 1))
x_y_index = 0
for x_index, x_value in enumerate(x_axis):
for y_index, y_value in enumerate(y_axis):
x_predictions[x_y_index] = x_value
y_predictions[x_y_index] = y_value
x_y_index += 1
z_predictions = linear_regression.predict(np.hstack((x_predictions, y_predictions)))
plot_predictions_trace = go.Scatter3d(
x=x_predictions.flatten(),
y=y_predictions.flatten(),
z=z_predictions.flatten(),
name='Prediction Plane',
mode='markers',
marker={
'size': 1,
},
opacity=0.8,
surfaceaxis=2,
)
plot_data = [plot_training_trace, plot_test_trace, plot_predictions_trace]
plot_figure = go.Figure(data=plot_data, layout=plot_layout)
plotly.offline.plot(plot_figure)
模型评估:
逻辑回归:
二分类算法,决策边界可以非线性
sigmod函数:
红色为其自身图像,另外是其导数图像,自变量取值任意实数,值域[0,1],将任意输入映射到区间[0,1],在线性回归中得到一个预测值,再将该值映射到sigmod函数中,就完成值到该来的转换,预测函数(其中):
分类任务:
聚类(二分类、多分类)
贝叶斯算法
支持向量机SVM
决策树
神经网络
CV
CNN
RNN
GAN
LSTM
Transformer
数据校验规则
大数据迁移
业务分析
数据开发(字段,报表,归因,口径,取数验证,系统部署)
数据分析