纯python实现线性回归——以各国人均GDP变化为例
本项目使用纯python从csv数据处理和基本原理讲解开始理解线性回归。
注意:因为本例只是一个学习案例,人均GDP的变化影响因素很多,本例只做了简单的线性回归,所以不需要深究,明白相应的线性回归道理就行。
一、线性回归
回归是监督学习的一个重要问题,回归用于预测输入变量和输出变量之间的关系,特别是当输入变量的值发生变化时,输出变量的值也随之发生变化。回归模型正是表示从输入变量到输出变量之间映射的函数。
线性回归详细介绍,下面就让我们通过纯python代码来理解线性回归
二、人均GDP线性回归实战
# 导入相应的包
from random import seed
from random import randrange
from csv import reader
from math import sqrt
1、数据处理和可视化
本例主要是对CSV文件的处理,因为读取csv中的文件数据是字符型所以要转换成浮点数。然后再将数据划分成训练集和测试集。
这是数据的具体结构:
# 导入CSV文件
def load_csv(filename):
dataset = list()
with open(filename, 'r') as file:
csv_reader = reader(file)
# 读取表头X,Y
headings = next(csv_reader)
# 文件指针下移至第一条真正的数据
for row in csv_reader:
if not row:
continue
dataset.append(row)
return dataset
# 将字符串列转换为浮点数,将column列转换为浮点数
def str_column_to_float(dataset, column):
for row in dataset:
row[column] = float(row[column].strip()) # strip()方法移除字符串头尾指定的字符
# 将数据集分割为训练集合和测试集合两部分(比例分割)
def train_test_split(dataset, percent):
train = list()
train_size = percent * 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 # dataset_copy相当于测试集
from matplotlib import pyplot as plt
filename = 'data/data103309/line_animation.csv'
dataset = load_csv(filename)
# 看有多少列,将每一列字符转换为浮点数
for col in range(len(dataset[0])):
str_column_to_float(dataset, col)
time = [i[0] for i in dataset]
china = [i[1] for i in dataset]
usa =[i[2] for i in dataset]
king =[i[3] for i in dataset]
japan =[i[4] for i in dataset]
russia = [i[5] for i in dataset]
#根据数据绘制图形
fig=plt.figure(figsize=(20, 8), dpi=80)
plt.plot(time,china,label='china')
plt.plot(time,usa,label='usa')
plt.plot(time,king,label='king')
plt.plot(time,japan,label='japan')
plt.plot(time,russia,label='russia')
#设置图形格式
plt.title("Changes in GDP of each country",fontsize=20)
plt.xlabel('year',fontsize=16)
plt.ylabel('GDP',fontsize=16)
# 绘制网格
plt.grid(alpha=0.4)
#添加图例
plt.legend(loc="upper left")
plt.show()
2、协方差计算
# 计算均值
def mean(values):
return sum(values) / float(len(values))
# 计算方差
def variance(values, mean):
return sum([(x - mean) ** 2 for x in values])
# 计算协方差
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
3、构建简单线性回归
# 计算回归系数的函数
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)
w1 = covariance(x, x_mean, y, y_mean) / variance(x, x_mean)
w0 = y_mean - w1 * x_mean
return w0, w1
# 计算均方根误差RMSE
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)
# 构建简单线性回归
def simple_linear_regression(train, test):
predict = list()
w0, w1 = coefficients(train)
for row in test:
y_model = w1 * row[0] + w0
predict.append(y_model)
return predict
4、算法评估函数
# 使用分割开的训练集合和测试集运行评估算法
# *args存放元组参数,**args存放字典参数
def evaluate_algorithm(dataset, algorithm, split_percent, *args):
train, test = train_test_split(dataset, split_percent)
# dataset :[[1.2, 1.1], [2.4, 3.5], [4.1, 3.2], [3.4, 3.8], [5, 5.4]]变为
# test_set = [[1.2, None], [2.4, None], [4.1, None], [3.4, None], [5, None]]
test_set = list()
for row in test:
row_copy = list(row)
row_copy[-1] = None
test_set.append(row_copy)
# 用test_set计算出预测值,并和真实值一起带入函数
predicted = algorithm(train, test_set, *args)
actual = [row[-1] for row in test]
rmse = rmse_metric(actual, predicted)
return rmse
5、训练和评估
# 设置随机数种子,为随机挑选训练和测试数据集做准备
seed(2)
# 导入保险数据并做数据分割准备
filename = 'data/data103309/line_animation.csv'
dataset = load_csv(filename)
# 看有多少列,将每一列字符转换为浮点数
for col in range(len(dataset[0])):
str_column_to_float(dataset, col)
# 因为我们只训练中国的人均GDP所以取time和china两列就行
dataset = [[i[0],i[1]] for i in dataset]
# 设置数据集合分割百分比
percent = 0.6
rmse = evaluate_algorithm(dataset, simple_linear_regression, percent)
print('RMSE:{0:.3f}'.format(rmse))