本节为吴恩达教授机器学习笔记第一部分:线性回归最后一部分,包括:最小化J的统计学推导以及局部加权线性回归(含代码及一个应用例子)。
3. 统计学解释
假设输入与目标变量有如下关系:
其中
ϵ
(
i
)
\epsilon^{(i)}
ϵ(i)是一个误差项,用于捕获没有建模的影响因素,或者是随机噪音。更进一步地,假设该项独立同分布,并且符合正态分布,则有:
也就是说:
这个记号表示的是给定
x
(
i
)
x^{(i)}
x(i)和
θ
\theta
θ时
y
(
i
)
y^{(i)}
y(i)的分布情况,因为
θ
\theta
θ不是随机变量,所以也可以写为:
给定输入与参数
θ
\theta
θ的条件下,
y
y
y的概率为:
利用似然函数:
在变量互相独立的前提下有:
在给定上述概率模型的情况下,可以通过极大似然方法来选择
θ
\theta
θ的值,使得数据概率更高,为此,可以通过最大化极大似然函数的对数似然函数,有:
可以看出,最大化对数似然函数也就是最小化
至此,概率方法给出了和我们原始最小均方代价函数相同的答案。
4. 局部加权线性回归
原始线性回归算法的过程是:
局部加权线性回归则是:
其中
ω
(
i
)
\omega ^{(i)}
ω(i)是非负权重,如果权重过大,很难减小
J
J
J的值,如果权重很小,误差项就会很容易忽略,一个折中的选择是:
可以看出距离待确定样本越远,权重越小,公式中参数
τ
\tau
τ为bandwidth参数,表示分布最大值到最小值变化的速度,越大,变小越快,分布的图形就越“尖锐”。
局部加权线性回归不同于标准线性回归,其是一种无参数算法。标准线性回归中,得到参数
θ
\theta
θ之后的预测过程,是不需要训练数据集参与的,而局部加权线性回归则依赖于训练集,这样会导致运算量的增加,为此有KDTree方法来优化(《统计学习方法》第三章)。
之前闲的无聊,用局部加权线性回归还跑过一个不小的数据集,如下,核心的代码很简单,但是处理数据花的时间就老长了,感兴趣可以看看数据集和全部的预处理代码,链接在此。
from Preprocess import *
from numpy import *
from scipy import linalg
class Train:
def __init__(self):
self.prepro = PrePro()
self.matrix_complete = self.prepro.process_train()
self.feature_train, self.feature_test, self.label_train, self.label_test, self.traindata, self.labelVector \
= self.prepro.generate(self.matrix_complete)
def lwlr(self, testPoint, xArr, yArr, k):
# xMat = np.mat(xArr)
# yMat = np.mat(yArr).T
xMat = xArr
yMat = mat(yArr).T
m = shape(xMat)[0]
weights = mat(eye((m)))
for j in range(m):
diffMat = testPoint - xMat[j, :]
diffMat = mat(diffMat)
a = diffMat * diffMat.T / (-2.0 * k ** 2)
weights[j, j] = math.exp(a)
xTx = xMat.T * (weights * xMat)
temp_d=zeros([2,2])
temp_d[0][0]=xTx[0].tolist()[0][0]
temp_d[0][1]=xTx[0].tolist()[0][1]
temp_d[1][0]=xTx[1].tolist()[0][0]
temp_d[1][1]=xTx[1].tolist()[0][1]
xTx=temp_d
xTx=mat(xTx)
if linalg.det(xTx) == 0.0:
print("This matrix is singular, cannot do inverse")
return
ws = xTx.I * (xMat.T * (weights * yMat))
return testPoint * ws
def lwlrTest(self, testArr, xArr, yArr, k=1.0): # loops over all the data points and applies lwlr to each one
m = shape(testArr)[0]
yHat = zeros(m)
for i in range(m):
yHat[i] = self.lwlr(testArr[i], xArr, yArr, k)
return yHat
if __name__ == '__main__':
trainer = Train()
temp=0
y_hat = trainer.lwlrTest(trainer.feature_test, trainer.feature_train, trainer.label_train, k=0.3)
for i in range(len(y_hat)):
temp=temp+(y_hat[i]-trainer.label_test[i])**2
score=temp/(len(y_hat))
score=math.sqrt(score)
print(score)
#print(trainer.label_test,y_hat)
另外还有一个用tensorflow写的线性回归,链接在此,代码如下:
# -*-coding:utf-8-*-
import random
import numpy as np
import tensorflow as tf
import tensorflow.contrib.eager as tfe
# 开启eager API
tfe.enable_eager_execution()
# 生成数据
num_inputs = 2
num_examples = 1000
true_w = [2, -3.4]
true_b = 4.2
tmp_list1 = [np.random.normal() for i in range(num_examples)]
tmp_list2 = [np.random.normal() for i in range(num_examples)]
features = np.vstack((tmp_list1, tmp_list2)).transpose()
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
labels = labels + np.random.normal(scale=0.01)
labels = labels.reshape(1000, 1)
# 读取数据
batch_size = 10
# 每次随机读取十个数据
def data_iter(batch_size, features, labels):
num_examples = len(features)
indices = list(range(num_examples))
# 样本的读取顺序是随机的。
random.shuffle(indices)
for i in range(0, num_examples, batch_size):
j = np.array(indices[i: min(i + batch_size, num_examples)])
# take 函数根据索引返回对应元素。
yield np.hstack(
((features[:, 0].take(j)).reshape(-1, 1), (features[:, 1].take(j)).reshape(-1, 1))), labels.take(j)
# 权重和偏置
W = tfe.Variable(np.array([np.random.randn() for i in range(2)]).reshape(2, 1))
b = tfe.Variable(np.array(np.random.randn()))
# 线性回归公式函数(Wx + b)
def linear_regression(inputs):
return tf.add(tf.matmul(inputs
, W), b)
# 均方误差函数,计算损失
def mean_square_fn(model_fn, inputs, labels):
return tf.reduce_sum(tf.pow(model_fn(inputs) - labels, 2)) / (2 * num_examples)
# 参数
learning_rate = 0.01
display_step = 100
num_epochs_random_data = 3
num_epochs_entire_data = 3000
# 随机梯度下降法作为优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
# 计算梯度
grad = tfe.implicit_gradients(mean_square_fn)
# 优化之前,初始化损失函数
print("Initial cost= {:.5f}".format(
mean_square_fn(linear_regression, features, labels)),
"W=", W.numpy(), "b=", b.numpy())
# 每次选取全部数据训练
for step in range(num_epochs_entire_data):
optimizer.apply_gradients(grad(linear_regression, features, labels))
if (step + 1) % display_step == 0 or step == 0:
print "Epoch:", '%d' % (step + 1), \
"\n", "cost=", "{:.5f}".format(mean_square_fn(linear_regression, features, labels)), \
"\n", "W=", W.numpy(), "\n", \
"b=", b.numpy()
欢迎扫描二维码关注微信公众号 深度学习与数学 [每天获取免费的大数据、AI等相关的学习资源、经典和最新的深度学习相关的论文研读,算法和其他互联网技能的学习,概率论、线性代数等高等数学知识的回顾]