Сегодня давайте начнем с машинного обучения и кратко представим модель линейной регрессии.
В последние несколько дней люди спрашивали меня о подгонке данных, а также о моделях прогнозирования и т. д., поэтому я хочу начать эту колонку, которую я готовил некоторое время — машинное обучение.
Линейная регрессия — это линейная модель, например модель, которая предполагает линейную связь между входной переменной (x) и одной выходной переменной (y).
Более конкретно, выходная переменная (y) может быть вычислена из линейной комбинации входных переменных (x).
Поэтому мы хотим, чтобы алгоритм изучил гипотетические параметры, чтобы он мог построить уравнение для прогнозирования, которое принимает признаки и параметры в качестве входных данных и предсказывает их значение в качестве выходных данных.
Чтобы понять линейную регрессию, мы должны начать с математики, стоящей за ней.
1. Математические принципы
Мы знакомимся с уравнениями с младших классов средней школы: сначала это было просто y=kx+b, а потом оно становилось все сложнее и сложнее. Сталкивались ли вы с такой проблемой в средней школе? Название дает много дневного объема продаж и прибыли торгового центра, и вы можете получить от него функцию для оценки прибыли от определенного объема продаж в будущем. Или когда в вузе проводят крупномасштабные опыты и рисование, преподаватель всегда говорит, что требование к рисованию линии состоит в том, чтобы провести прямую линию так, чтобы каждая точка была равномерно распределена по обеим сторонам прямой линии, а расстояние до прямая самая короткая. Итак, какая прямая линия лучше всего подходит для предсказания кривой этих характеристик данных (атрибутов)? Здесь нам нужно поговорить о линейных моделях.
Первая - самая основная форма выражениягде X — индивидуальные свойства независимой переменной, а θ — параметр Дальше самое главное, как оптимизировать параметры, то есть минимизировать процент потерь. Это должно говорить о коэффициенте потерь и функции потерь, Функция потерь, которую мы выбираем здесь, является среднеквадратичной ошибкой.С функцией потерь мы должны найти способ минимизировать ошибку. Чтобы найти минимальное значение функции, требуется еще один очень важный алгоритм, называемый градиентным спуском.
градиентный спуск: Градиентный спуск — это итеративный алгоритм оптимизации, используемый для нахождения функции минимальных потерь. Для нахождения функции локального минимума потерь используется алгоритм градиентного спуска, аппроксимируемый определенной долей шагов отрицательного градиента функции в текущей точке.
На рисунке ниже показаны шаги, которые мы предпринимаем, чтобы найти локальный минимум, начиная с верхней точки функции.Под отрицательным градиентом функции понимается отрицательное направление вывода функции потерьТогда размер шага каждого обновления — это то, что мы называем скоростью обучения, так что минимальное значение функции потерь можно найти с помощью итерации и получить решение с оптимальным параметром.
Здесь есть проблема, что градиентный спуск легко попасть в локальный минимум, а не в глобальный минимум, который включает в себя алгоритмы оптимизации, такие как стохастический градиентный спуск, а также переобучение и, таким образом, теряет способность обобщать
Часть реализации кода
Первый — самый простой метод линейной подгонки.Возьмем, к примеру, домашнее задание, которое вы делаете за кого-то другого.
import pandas as pd
import numpy as np
import math
from scipy.optimize import leastsq
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
#导入数据
#平方英尺
x=[150,200,250,300,350,400,600]
#房价
y=[6450,7450,8450,9450,11450,15450,18450]
#训练集和测试集
x_train=np.array(x[0:5])
y_train=np.array(y[0:5])
x_test=np.array(x[5:7])
y_test=np.array(y[5:7])
def fun(p,x):
k,b=p
return k*x+b
# 误差函数
def error(p,x,y):
return np.sqrt((fun(p,x)-y)**2)
#只用前五个数据进行预测
p0=[100,2]
para=leastsq(error,p0,args=(x_train,y_train))
k,b=para[0]
print("拟合的方程为:y={}x+{}".format(k,b))
#绘制拟合直线
plt.figure(figsize=(8,6))
plt.scatter(x,y,color="red",label="Point",linewidth=3)
X=np.linspace(100,700,1000)
Y=k*X+b
plt.plot(X,Y,color="orange",label="拟合直线",linewidth=2)
plt.xlabel('平方英尺')
plt.ylabel('房价')
plt.legend()
plt.show()
#画误差图
err1=[]
for i in range(len(x_train)):
err1.append(k*x_train[i]+b-y_train[i])
plt.figure(figsize=(10, 7))
plt.title('误差图')
plt.plot(x_train,err1,'r',label='error', linewidth=3)
plt.xlabel('x')
plt.ylabel('error')
plt.show()
Затем напишите фрагмент кода, имитируя линейную модель sklearn, и создайте собственный тренажер линейной модели.Используемый здесь набор данных — это данные World Happiness Index и GPD за 2017 год, которые можно скачать на kaggle, ссылка выглядит следующим образом. Woohoo. Карта изменена. SN на com/UN/Я смирился с этим…Затем мы используем индекс ВВП, чтобы предсказать индекс счастья людей.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#导入数据
data = pd.read_csv('2017.csv')
#查看数据集
data.info()
data.head(10)
#画出每一个属性的分布直方图
histohrams = data.hist(grid=False, figsize=(10, 10))
#切分训练集和测试集
#分出80%训练集,20%测试集
#这里没有用到sklearn的train_test_split
train_data = data.sample(frac=0.8)
test_data = data.drop(train_data.index)
x_train = train_data[['Economy..GDP.per.Capita.']].values
y_train = train_data[['Happiness.Score']].values
x_test = test_data[['Economy..GDP.per.Capita.']].values
y_test = test_data[['Happiness.Score']].values
#绘制出散点图
plt.scatter(x_train, y_train, label='Training Dataset')
plt.scatter(x_test, y_test, label='Test Dataset')
plt.xlabel('Economy..GDP.per.Capita.')
plt.ylabel('Happiness.Score')
plt.title('Countries Happines')
plt.legend()
plt.show()
Затем есть некоторые функции регуляризации для предотвращения переобучения и функции нормализации, которые не будут здесь публиковаться.
#开始自己动手写一个线性回归模型
class self_LinearRegression:
def __init__(self, data, labels, polynomial_degree=0, sinusoid_degree=0, normalize_data=True):
(data_processed,features_mean,features_deviation)=prepare_for_training(data, polynomial_degree, sinusoid_degree, normalize_data)
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]
self.theta = np.zeros((num_features, 1))
#训练
def train(self, alpha, lambda_param=0, num_iterations=500):
cost_history = self.gradient_descent(alpha, lambda_param, num_iterations)
return self.theta, cost_history
#梯度下降
def gradient_descent(self, alpha, lambda_param, num_iterations):
cost_history = []
for _ in range(num_iterations):
self.gradient_step(alpha, lambda_param)
cost_history.append(self.cost_function(self.data, self.labels, lambda_param))
return cost_history
def gradient_step(self, alpha, lambda_param):
num_examples = self.data.shape[0]
predictions = self_LinearRegression.hypothesis(self.data, self.theta)
delta = predictions - self.labels
reg_param = 1 - alpha * lambda_param / num_examples
theta = self.theta
theta = theta * reg_param - alpha * (1 / num_examples) * (delta.T @ self.data).T
theta[0] = theta[0] - alpha * (1 / num_examples) * (self.data[:, 0].T @ delta).T
self.theta = theta
#损失率
def get_cost(self, data, labels, lambda_param):
data_processed = prepare_for_training(
data,
self.polynomial_degree,
self.sinusoid_degree,
self.normalize_data,
)[0]
return self.cost_function(data_processed, labels, lambda_param)
def cost_function(self, data, labels, lambda_param):
num_examples = data.shape[0]
delta = self_LinearRegression.hypothesis(data, self.theta) - labels
theta_cut = self.theta[1:, 0]
reg_param = lambda_param * (theta_cut.T @ theta_cut)
cost = (1 / 2 * num_examples) * (delta.T @ delta + reg_param)
return cost[0][0]
#预测
def predict(self, data):
data_processed = prepare_for_training(
data,
self.polynomial_degree,
self.sinusoid_degree,
self.normalize_data,
)[0]
predictions = self_LinearRegression.hypothesis(data_processed, self.theta)
return predictions
@staticmethod
def hypothesis(data, theta):
predictions = data @ theta
return predictions
#现在开始训练自己做的线性回归模型
num_iterations = 500 #设置迭代次数
learning_rate = 0.01 #学习率
regularization_param = 0 #正则化参数
polynomial_degree = 0
sinusoid_degree = 0
linear_regression = self_LinearRegression(x_train, y_train, polynomial_degree, sinusoid_degree)
(theta, cost_history) = linear_regression.train(learning_rate,regularization_param,num_iterations)
#输出训练的损失率
print('最初损失率: {:.2f}'.format(cost_history[0]))
print('最优损失率: {:.2f}'.format(cost_history[-1]))
#输出模型参数
theta_table = pd.DataFrame({'自己的线性模型参数': theta.flatten()})
theta_table.head()
Уравнение линейной регрессии, полученное путем обучения модели, написанной вами, имеет вид: y=5,383319*x+0,892002.
#画出梯度下降
plt.plot(range(num_iterations), cost_history)
plt.xlabel('迭代次数')
plt.ylabel('损失率')
plt.title('损失率梯度下降图')
plt.show()
#用自己构建的模型去进行预测,绘制出模型预测直线
predictions_num = 100
x_predictions = np.linspace(x_train.min(), x_train.max(), predictions_num).reshape(predictions_num, 1)
y_predictions = linear_regression.predict(x_predictions)
plt.scatter(x_train, y_train, label='训练数据')
plt.scatter(x_test, y_test, label='测试数据')
plt.plot(x_predictions, y_predictions, 'r', label='预测直线')
plt.xlabel('Economy..GDP.per.Capita.')
plt.ylabel('Happiness.Score')
plt.title('Countries Happines')
plt.legend()
plt.show()
Затем используйте линейную регрессию sklrean для обучения и прогнозирования.
#用sklearn构建线性回归模型
from sklearn.linear_model import LinearRegression
#创建模型
liner = LinearRegression()
#拟合模型
liner.fit(x_train,y_train)
#预测
y_predictions = liner.predict(x_predictions)
plt.scatter(x_train, y_train, label='训练数据')
plt.scatter(x_test, y_test, label='测试数据')
plt.plot(x_predictions, y_predictions, 'r', label='预测直线')
plt.xlabel('Economy..GDP.per.Capita.')
plt.ylabel('Happiness.Score')
plt.title('Countries Happines')
plt.legend()
plt.show()
print("斜率为:",liner.coef_)
print("截距为:",liner.intercept_)