假设样本空间为
个维度,用
={
}来表示一个样本点,线性回归的目标是用
个参数来拟合样本点的输入和输出。通常我们会将
扩充为
维的向量
={
},第
设为1作为偏置项。线性回归表达式如下:
用向量可以表示为:
将表达式代入均方误差函数 中:
令全部样本表示为: ={ } ,对应输出表示为 ={ } ,损失函数可以简化为:
我们的目标是让损失函数最小,令其对 的偏导数为0,则有:
解得: 。
显然, 要是可逆的,通常情况下都能满足因为 。事实上 也存在不可逆的情况,这种情况下我们可以选择求 伪逆或者梯度下降法来解决问题。
如果要利用线性回归来解决二分类问题, 就不再是连续值,而是1(正样本)或者0/-1(负样本)。同样的求出权重向量后对测试样本进行预测,可以用0.5/0作为阈值来划分正负样本。
代码块
理解了线性回归和梯度下降的基本原理,用python撸出来也就10分钟的时间:
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import scale
from random import random
from sklearn.model_selection import train_test_split
class LinearRegression(object):
weight = np.array([])
way = 'gd'
def __init__(self, training_way = 'gd'):
self.way = training_way
def gradientDescent(self, X, Y, alpha, epoch):
W = np.random.normal(0,1,size=(X.shape[1],))
for i in range(epoch):
W -= alpha*(X.T).dot(X.dot(W)-Y)/X.shape[0]
return W
def fit(self, train_data, train_target, alpha = 0.1, epoch = 300):
X = np.ones((train_data.shape[0], train_data.shape[1]+1))
X[:,0:-1] = train_data
Y = train_target
if self.way == 'gd':
self.weight = self.gradientDescent(X, Y, alpha, epoch)
else:
self.weight = np.linalg.inv((X.T).dot(X)).dot(X.T).dot(Y)
def predict(self, test_data):
X = np.ones((test_data.shape[0], test_data.shape[1]+1))
X[:,0:-1] = test_data
return X.dot(self.weight)
def evaluate(self, predict_target, test_target):
predict_target[predict_target>=0.5] = 1
predict_target[predict_target<0.5] = 0
return sum(predict_target==test_target)/len(predict_target)
if __name__ == "__main__":
cancer = load_breast_cancer()
xtr, xval, ytr, yval = train_test_split(cancer.data, cancer.target, \
test_size=0.2, random_state=7)
linear = LinearRegression(training_way = 'gd')
linear.fit(xtr, ytr, alpha = 0.05, epoch = 1000)
predict = linear.predict(xval)
print('linear regression accruacy:',linear.evaluate(predict, yval))