如何用Python从零开始实现简单的线性回归

时间:2022-04-27
本文章向大家介绍如何用Python从零开始实现简单的线性回归,主要内容包括描述、瑞典保险数据库、教程、2.计算协方差、3.估计系数、做预测、5.预测保险、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

线性回归是一种超过200年的预测方法。

简单的线性回归是一个很好的机器学习算法来供我们实践入门,因为它需要你从你的训练数据集中估计属性,但是对于初学者来说很容易理解。

在本教程中,您将了解如何在Python中从头开始实现简单的线性回归算法。

完成本教程后,您将知道:

  • 如何从训练数据中估计统计量。
  • 如何从数据估计线性回归系数。
  • 如何使用线性回归预测新数据。

让我们开始吧。

如何使用Python实现简单的线性回归 Photo by Kamyar Adl,部分权利保留。

描述

本节分为两部分,第一部分介绍简单的线性回归技术,第二部分介绍稍后将应用到的数据集。

简单线性回归

线性回归假定是输入变量(X)和单个输出变量(y)之间的线性关系或直线关系。

更具体地说,输出变量(y)可以从输入变量(X)的线性组合来计算。当有一个输入变量时,该方法被称为简单线性回归。

在简单线性回归中,我们可以使用训练数据的统计数据来估计模型所需的系数,以便对新数据进行预测。

简单线性回归模型的线可以写成:

y = b0 + b1 * x

其中b0和b1是我们必须从训练数据估计的系数。

一旦系数已知,我们可以使用这个方程来估计y的输出值,给出x的新输入例子。

它要求您根据数据计算统计特性,如均值,方差和协方差。

所有的代数都已经被处理了,我们剩下一些算术实现来估计简单的线性回归系数。

简而言之,我们可以估算系数如下:

B1 = sum((x(i) - mean(x)) * (y(i) - mean(y))) / sum( (x(i) - mean(x))^2 )
B0 = mean(y) - B1 * mean(x)

其中i是指输入x或输出y的第i个值的值。

如果现在还不清楚,不要担心,这些是在教程中实现的功能。

瑞典保险数据库

我们将使用一个真实的数据集来演示简单的线性回归。

该数据集被称为“瑞典的汽车保险”数据集,并且涉及以千瑞典克朗(y)为单位预测所有索赔的总付款额(x)。

这意味着对于新数量的索赔(x),我们将能够预测索赔总额(y)。

这里是数据集前5条记录的一个小样本。

108,392.5
19,46.2
13,15.7
124,422.2
40,119.4

使用零规则算法(预测平均值),预期约72.251(千克朗)的均方根误差或RMSE。

以下是整个数据集的散点图。

瑞典保险数据库

您可以从这里这里下载原始数据集。

将其保存到本地工作目录中名为“ insurance.csv ” 的CSV文件中。

请注意,您可能需要将欧洲“,”转换为小数点“。”。您还需要将文件从空格分隔的变量更改为CSV格式。

教程

本教程分为五个部分:

  1. 计算均值和方差。
  2. 计算协方差。
  3. 估计系数。
  4. 作出预测。
  5. 预测保险。

这些步骤将为您提供实施和训练简单线性回归模型以预测自己的问题的基础。

1.计算均值和方差

第一步是估计来自训练数据的输入和输出变量的均值和方差。

数字列表的平均值可以计算如下:

mean(x) = sum(x) / count(x)

下面是一个名为mean()的函数,它为数字列表实现了这种行为。

# Calculate the mean value of a list of numbers
def mean(values):
return sum(values) / float(len(values))

方差是平均值中每个值的总和平方差。

数字列表的差异可以计算如下:

variance = sum( (x - mean(x))^2 )

下面是一个名为variance()的函数 ,用于计算数字列表的方差。它要求将列表的意思作为参数提供,所以我们不必多次计算它。

# Calculate the variance of a list of numbers
def variance(values, mean):
return sum([(x-mean)**2 for x in values])

我们可以把这两个函数放在一起,在一个小小的数据集上进行测试。

以下是x和y值的小数据集。

:如果将其保存到.CSV文件以与最终代码示例一起使用,请从该数据中删除列标题。

x, y
1, 1
2, 3
4, 3
3, 2
5, 5

我们可以在散点图上绘制这个数据集,如下所示:

简单线性回归的小型数据集

我们可以在下面的例子中计算x和y值的均值和方差。

# Estimate Mean and Variance
# Calculate the mean value of a list of numbers
def mean(values):
return sum(values) / float(len(values))
# Calculate the variance of a list of numbers
def variance(values, mean):
return sum([(x-mean)**2 for x in values])
# calculate mean and variance
dataset = [[1, 1], [2, 3], [4, 3], [3, 2], [5, 5]]
x = [row[0] for row in dataset]
y = [row[1] for row in dataset]
mean_x, mean_y = mean(x), mean(y)
var_x, var_y = variance(x, mean_x), variance(y, mean_y)
print('x stats: mean=%.3f variance=%.3f' % (mean_x, var_x))
print('y stats: mean=%.3f variance=%.3f' % (mean_y, var_y))

运行这个例子打印出两列的均值和方差。

x stats: mean=3.000 variance=10.000
y stats: mean=2.800 variance=8.800

这是我们的第一步,接下来我们需要把这些值用于计算协方差。

2.计算协方差

两组数字的协方差描述了这些数字如何一起变化。

协方差是相关性的推广。相关性描述了两组数字之间的关系,而协方差可以描述两组或更多组之间的关系。

另外,可以将协方差标准化以产生相关值。

不过,我们可以计算两个变量之间的协方差如下:

covariance = sum((x(i) - mean(x)) * (y(i) - mean(y)))

下面是一个名为covariance()的函数,它实现了这个统计量。它建立在前面的步骤上,并将x和y值的列表以及这些值的平均值作为参数。

# Calculate covariance between x and y
def covariance(x, mean_x, y, mean_y):
covar = 0.0
for i in range(len(x)):
covar += (x[i] - mean_x) * (y[i] - mean_y)
return covar

我们可以在前面的小节中测试同样的小设计数据集的协方差的计算。

把它放在一起,我们得到下面的例子。

# Calculate Covariance
# Calculate the mean value of a list of numbers
def mean(values):
return sum(values) / float(len(values))
# Calculate covariance between x and y
def covariance(x, mean_x, y, mean_y):
covar = 0.0
for i in range(len(x)):
covar += (x[i] - mean_x) * (y[i] - mean_y)
return covar
# calculate covariance
dataset = [[1, 1], [2, 3], [4, 3], [3, 2], [5, 5]]
x = [row[0] for row in dataset]
y = [row[1] for row in dataset]
mean_x, mean_y = mean(x), mean(y)
covar = covariance(x, mean_x, y, mean_y)
print('Covariance: %.3f' % (covar))

运行此示例将打印x和y变量的协方差。


Covariance: 8.000

现在我们已经完成了所有的计算我们模型的系数。

3.估计系数

我们必须用简单线性回归来估计两个系数的值。

首先是B1,可以估计为:

B1 = sum((x(i) - mean(x)) * (y(i) - mean(y))) / sum( (x(i) - mean(x))^2 )

我们已经学习了上面的一些东西,可以简化这个算法:


B1 = covariance(x, y) / variance(x)

我们已经有函数来计算协方差()方差()

接下来,我们需要估计B0的值,也称为截距,因为它控制与y轴相交的线的起始点。


B0 = mean(y) - B1 * mean(x)

再次,我们知道如何估计B1,我们有一个函数来估计mean()

我们可以把所有这些放到一个名为coefficients()的函数中,该函数将数据集作为参数并返回系数。

# Calculate coefficients
def coefficients(dataset):
x = [row[0] for row in dataset]
y = [row[1] for row in dataset]
x_mean, y_mean = mean(x), mean(y)
b1 = covariance(x, x_mean, y, y_mean) / variance(x, x_mean)
b0 = y_mean - b1 * x_mean
return [b0, b1]

我们可以把前面两步的所有功能放在一起,并测试系数的计算。

# Calculate Coefficients
# Calculate the mean value of a list of numbers
def mean(values):
return sum(values) / float(len(values))
# Calculate covariance between x and y
def covariance(x, mean_x, y, mean_y):
covar = 0.0
for i in range(len(x)):
covar += (x[i] - mean_x) * (y[i] - mean_y)
return covar
# Calculate the variance of a list of numbers
def variance(values, mean):
return sum([(x-mean)**2 for x in values])
# Calculate coefficients
def coefficients(dataset):
x = [row[0] for row in dataset]
y = [row[1] for row in dataset]
x_mean, y_mean = mean(x), mean(y)
b1 = covariance(x, x_mean, y, y_mean) / variance(x, x_mean)
b0 = y_mean - b1 * x_mean
return [b0, b1]
# calculate coefficients
dataset = [[1, 1], [2, 3], [4, 3], [3, 2], [5, 5]]
b0, b1 = coefficients(dataset)
print('Coefficients: B0=%.3f, B1=%.3f' % (b0, b1))

运行这个例子计算和打印系数。

Coefficients: B0=0.400, B1=0.800

现在我们知道如何估计系数,下一步就是使用它们。

做预测

简单线性回归模型是由训练数据估计的系数定义的线。

一旦估计了系数,我们就可以用它们做出预测。

用简单的线性回归模型进行预测的方程如下:

y = b0 + b1 * x

下面是一个名为simple_linear_regression()的函数,它实现了对测试数据集进行预测的预测方程。它还将来自上述步骤的训练数据的系数估计联系在一起。

训练数据中准备的系数用于对测试数据进行预测,然后返回。

def simple_linear_regression(train, test):
predictions = list()
b0, b1 = coefficients(train)
for row in test:
yhat = b0 + b1 * row[0]
predictions.append(yhat)
return predictions

让我们把我们所学的所有东西放在一起,并对我们简单的人工数据集做出预测。

作为这个例子的一部分,我们还将添加一个函数来管理对evaluate_algorithm()的预测的评估,另一个函数用于估计称为rmse_metric()的预测的均方根误差。

完整的例子如下所示。

# Standalone simple linear regression example
from math import sqrt
# Calculate root mean squared error
def rmse_metric(actual, predicted):
sum_error = 0.0
for i in range(len(actual)):
prediction_error = predicted[i] - actual[i]
sum_error += (prediction_error ** 2)
mean_error = sum_error / float(len(actual))
return sqrt(mean_error)
# Evaluate regression algorithm on training dataset
def evaluate_algorithm(dataset, algorithm):
test_set = list()
for row in dataset:
row_copy = list(row)
row_copy[-1] = None
test_set.append(row_copy)
predicted = algorithm(dataset, test_set)
print(predicted)
actual = [row[-1] for row in dataset]
rmse = rmse_metric(actual, predicted)
return rmse
# Calculate the mean value of a list of numbers
def mean(values):
return sum(values) / float(len(values))
# Calculate covariance between x and y
def covariance(x, mean_x, y, mean_y):
covar = 0.0
for i in range(len(x)):
covar += (x[i] - mean_x) * (y[i] - mean_y)
return covar
# Calculate the variance of a list of numbers
def variance(values, mean):
return sum([(x-mean)**2 for x in values])
# Calculate coefficients
def coefficients(dataset):
x = [row[0] for row in dataset]
y = [row[1] for row in dataset]
x_mean, y_mean = mean(x), mean(y)
b1 = covariance(x, x_mean, y, y_mean) / variance(x, x_mean)
b0 = y_mean - b1 * x_mean
return [b0, b1]
# Simple linear regression algorithm
def simple_linear_regression(train, test):
predictions = list()
b0, b1 = coefficients(train)
for row in test:
yhat = b0 + b1 * row[0]
predictions.append(yhat)
return predictions
# Test simple linear regression
dataset = [[1, 1], [2, 3], [4, 3], [3, 2], [5, 5]]
rmse = evaluate_algorithm(dataset, simple_linear_regression)
print('RMSE: %.3f' % (rmse))

运行此示例将显示以下输出,其中首先列出这些预测的预测和RMSE。

[1.1999999999999995, 1.9999999999999996, 3.5999999999999996, 2.8, 4.3999999999999995]
RMSE: 0.693

最后,我们可以将预测作为一条线,并将其与原始数据集进行比较。

简单线性回归的小型数据集预测

5.预测保险

我们现在知道如何实现一个简单的线性回归模型。

让我们将其应用于瑞典保险数据集。

本节假设您已将数据集下载到文件insurance.csv,并且该文件在当前工作目录中可用。

从前面的步骤我们将添加一些便利功能到简单的线性回归。

具体来说就是加载名为load_csv()的CSV文件的函数,该函数是将加载的数据集转换为名为str_column_to_float()的函数,函数使用train和测试集来评估算法train_test_split()函数来计算RMSE,称为rmse_metric ()和函数来评估一个名为evaluate_algorithm()的算法。

完整的例子如下所示。

使用60%的数据的训练数据集来准备模型,并对剩下的40%进行预测。

# Simple Linear Regression on the Swedish Insurance Dataset
from random import seed
from random import randrange
from csv import reader
from math import sqrt
# Load a CSV file
def load_csv(filename):
dataset = list()
with open(filename, 'r') as file:
csv_reader = reader(file)
for row in csv_reader:
if not row:
continue
dataset.append(row)
return dataset
# Convert string column to float
def str_column_to_float(dataset, column):
for row in dataset:
row[column] = float(row[column].strip())
# Split a dataset into a train and test set
def train_test_split(dataset, split):
train = list()
train_size = split * len(dataset)
dataset_copy = list(dataset)
while len(train) < train_size:
index = randrange(len(dataset_copy))
train.append(dataset_copy.pop(index))
return train, dataset_copy
# Calculate root mean squared error
def rmse_metric(actual, predicted):
sum_error = 0.0
for i in range(len(actual)):
prediction_error = predicted[i] - actual[i]
sum_error += (prediction_error ** 2)
mean_error = sum_error / float(len(actual))
return sqrt(mean_error)
# Evaluate an algorithm using a train/test split
def evaluate_algorithm(dataset, algorithm, split, *args):
train, test = train_test_split(dataset, split)
test_set = list()
for row in test:
row_copy = list(row)
row_copy[-1] = None
test_set.append(row_copy)
predicted = algorithm(train, test_set, *args)
actual = [row[-1] for row in test]
rmse = rmse_metric(actual, predicted)
return rmse
# Calculate the mean value of a list of numbers
def mean(values):
return sum(values) / float(len(values))
# Calculate covariance between x and y
def covariance(x, mean_x, y, mean_y):
covar = 0.0
for i in range(len(x)):
covar += (x[i] - mean_x) * (y[i] - mean_y)
return covar
# Calculate the variance of a list of numbers
def variance(values, mean):
return sum([(x-mean)**2 for x in values])
# Calculate coefficients
def coefficients(dataset):
x = [row[0] for row in dataset]
y = [row[1] for row in dataset]
x_mean, y_mean = mean(x), mean(y)
b1 = covariance(x, x_mean, y, y_mean) / variance(x, x_mean)
b0 = y_mean - b1 * x_mean
return [b0, b1]
# Simple linear regression algorithm
def simple_linear_regression(train, test):
predictions = list()
b0, b1 = coefficients(train)
for row in test:
yhat = b0 + b1 * row[0]
predictions.append(yhat)
return predictions
# Simple linear regression on insurance dataset
seed(1)
# load and prepare data
filename = 'insurance.csv'
dataset = load_csv(filename)
for i in range(len(dataset[0])):
str_column_to_float(dataset, i)
# evaluate algorithm
split = 0.6
rmse = evaluate_algorithm(dataset, simple_linear_regression, split)
print('RMSE: %.3f' % (rmse))

运行算法打印训练数据集上的训练模型的RMSE。

得分约为38(千克朗),这比在同一问题上达到约72(千克朗)的零规则算法好得多。

RMSE: 38.339