def f(w, X): return np.sum((X.dot(w)**2)) / len(X) def df_math(w, X): return X.T.dot(X.dot(w)) * 2. / len(X) def df_debug(w, X, epsilon=0.0001): res = np.empty(len(w)) for i in range(len(w)): w_1 = w.copy() w_1[i] += epsilon w_2 = w.copy() w_2[i] -= epsilon res[i] = (f(w_1, X) - f(w_2, X)) / (2 * epsilon) return res def direction(w): return w / np.linalg.norm(w) def gradient_ascent(df, X, initial_w, eta, n_iters = 1e4, epsilon=1e-8): w = direction(initial_w) cur_iter = 0 while cur_iter < n_iters: gradient = df(w, X) last_w = w w = w + eta * gradient w = direction(w) # 注意1:每次求一个单位方向 if(abs(f(w, X) - f(last_w, X)) < epsilon): break cur_iter += 1 return w
时间: 2023-05-26 15:07:42 浏览: 105
这是一个用于实现梯度上升算法的Python函数。其中,f(w, X)用来计算代价函数的值,df_math(w, X)用来计算代价函数的梯度,df_debug(w, X, epsilon)是用来调试df_math(w, X)函数的,direction(w)用来保证梯度向量的方向为最大增加方向,gradient_ascent(df, X, initial_w, eta, n_iters = 1e4, epsilon=1e-8)是梯度上升算法的实现函数。其中,eta为学习率,n_iters为迭代次数,epsilon为收敛判断的临界值。
相关问题
import numpy as np from sklearn import datasets from sklearn.linear_model import LinearRegression np.random.seed(10) class Newton(object): def init(self,epochs=50): self.W = None self.epochs = epochs def get_loss(self, X, y, W,b): """ 计算损失 0.5sum(y_pred-y)^2 input: X(2 dim np.array):特征 y(1 dim np.array):标签 W(2 dim np.array):线性回归模型权重矩阵 output:损失函数值 """ #print(np.dot(X,W)) loss = 0.5np.sum((y - np.dot(X,W)-b)2) return loss def first_derivative(self,X,y): """ 计算一阶导数g = (y_pred - y)*x input: X(2 dim np.array):特征 y(1 dim np.array):标签 W(2 dim np.array):线性回归模型权重矩阵 output:损失函数值 """ y_pred = np.dot(X,self.W) + self.b g = np.dot(X.T, np.array(y_pred - y)) g_b = np.mean(y_pred-y) return g,g_b def second_derivative(self,X,y): """ 计算二阶导数 Hij = sum(X.T[i]X.T[j]) input: X(2 dim np.array):特征 y(1 dim np.array):标签 output:损失函数值 """ H = np.zeros(shape=(X.shape[1],X.shape[1])) H = np.dot(X.T, X) H_b = 1 return H, H_b def fit(self, X, y): """ 线性回归 y = WX + b拟合,牛顿法求解 input: X(2 dim np.array):特征 y(1 dim np.array):标签 output:拟合的线性回归 """ self.W = np.random.normal(size=(X.shape[1])) self.b = 0 for epoch in range(self.epochs): g,g_b = self.first_derivative(X,y) # 一阶导数 H,H_b = self.second_derivative(X,y) # 二阶导数 self.W = self.W - np.dot(np.linalg.pinv(H),g) self.b = self.b - 1/H_bg_b print("itration:{} ".format(epoch), "loss:{:.4f}".format( self.get_loss(X, y , self.W,self.b))) def predict(): """ 需要自己实现的代码 """ pass def normalize(x): return (x - np.min(x))/(np.max(x) - np.min(x)) if name == "main": np.random.seed(2) X = np.random.rand(100,5) y = np.sum(X3 + X**2,axis=1) print(X.shape, y.shape) # 归一化 X_norm = normalize(X) X_train = X_norm[:int(len(X_norm)*0.8)] X_test = X_norm[int(len(X_norm)*0.8):] y_train = y[:int(len(X_norm)0.8)] y_test = y[int(len(X_norm)0.8):] # 牛顿法求解回归问题 newton=Newton() newton.fit(X_train, y_train) y_pred = newton.predict(X_test,y_test) print(0.5np.sum((y_test - y_pred)**2)) reg = LinearRegression().fit(X_train, y_train) y_pred = reg.predict(X_test) print(0.5np.sum((y_test - y_pred)**2)) ——修改代码中的问题,并补全缺失的代码,实现牛顿最优化算法
好的,我根据代码中的问题进行了修改和补全缺失的部分,如下所示:
```
import numpy as np
from sklearn import datasets
from sklearn.linear_model import LinearRegression
np.random.seed(10)
class Newton(object):
def __init__(self, epochs=50):
self.W = None
self.b = None
self.epochs = epochs
def get_loss(self, X, y, W, b):
"""
计算损失 0.5sum(y_pred-y)^2
input:
X(2 dim np.array):特征
y(1 dim np.array):标签
W(2 dim np.array):线性回归模型权重矩阵
b(1 dim np.array):线性回归模型偏置
output:损失函数值
"""
y_pred = np.dot(X, W) + b
loss = 0.5 * np.sum((y_pred - y) ** 2)
return loss
def first_derivative(self, X, y):
"""
计算一阶导数g = (y_pred - y)*x
input:
X(2 dim np.array):特征
y(1 dim np.array):标签
output:损失函数值
"""
y_pred = np.dot(X, self.W) + self.b
g = np.dot(X.T, np.array(y_pred - y))
g_b = np.mean(y_pred - y)
return g, g_b
def second_derivative(self, X, y):
"""
计算二阶导数 H_ij = sum(X.T[i]X.T[j])
input:
X(2 dim np.array):特征
y(1 dim np.array):标签
output:损失函数值
"""
H = np.dot(X.T, X)
H_b = 1
return H, H_b
def fit(self, X, y):
"""
线性回归 y = WX + b拟合,牛顿法求解
input:
X(2 dim np.array):特征
y(1 dim np.array):标签
output:拟合的线性回归
"""
self.W = np.random.normal(size=(X.shape[1]))
self.b = 0
for epoch in range(self.epochs):
g, g_b = self.first_derivative(X, y)
H, H_b = self.second_derivative(X, y)
H_inv = np.linalg.inv(H)
self.W = self.W - np.dot(H_inv, g)
self.b = self.b - H_inv @ np.array([g_b])
print("itration:{} ".format(epoch), "loss:{:.4f}".format(self.get_loss(X, y, self.W, self.b)))
def predict(self, X):
"""
线性回归预测
input:
X(2 dim np.array):特征
output:预测结果
"""
y_pred = np.dot(X, self.W) + self.b
return y_pred
def normalize(x):
return (x - np.min(x)) / (np.max(x) - np.min(x))
if __name__ == "__main__":
np.random.seed(2)
X = np.random.rand(100, 5)
y = np.sum(X ** 3 + X ** 2, axis=1)
print(X.shape, y.shape)
# 归一化
X_norm = normalize(X)
X_train = X_norm[:int(len(X_norm) * 0.8)]
X_test = X_norm[int(len(X_norm) * 0.8):]
y_train = y[:int(len(X_norm) * 0.8)]
y_test = y[int(len(X_norm) * 0.8):]
# 牛顿法求解回归问题
newton = Newton()
newton.fit(X_train, y_train)
y_pred = newton.predict(X_test)
print("Newton Method MSE: ", 0.5 * np.sum((y_test - y_pred) ** 2))
# 对比sklearn中的线性回归
reg = LinearRegression().fit(X_train, y_train)
y_pred = reg.predict(X_test)
print("Linear Regression MSE: ", 0.5 * np.sum((y_test - y_pred) ** 2))
```
在这个修改后的代码中,我主要做了以下几个修改和补充:
1. 在 `__init__` 函数中,添加了 `self.b = None`,用于存储线性回归模型的偏置;
2. 在 `get_loss` 函数中,修正了计算损失的公式,将 `b` 加入到了计算中;
3. 在 `fit` 函数中,对牛顿法的求解进行了修改,使用了矩阵求逆的方式来计算 Hessian 矩阵的逆;
4. 在 `predict` 函数中,添加了 `X` 作为输入参数,用于进行预测;
5. 在主函数中,修改了求解 MSE 的计算公式,以及添加了输出方法,用于输出牛顿法求解和 sklearn 中线性回归的 MSE 值。
希望这些修改能够帮助你。
# 定义昂贵的函数 def expensive_func(t): return np.sum(t**2 - 10*np.cos(2*np.pi*t) + 10) # 定义高斯核函数 def gaussian_kernel(x, y, theta): return np.exp(-theta * cdist(x, y)**2) # 定义对数似然函数 def log_likelihood(params, x, y): theta, sigma = params k = gaussian_kernel(x, x, theta) + sigma**2 * np.eye(len(x)) try: L = np.linalg.cholesky(k) except np.linalg.LinAlgError: return -np.inf alpha = np.linalg.solve(L.T, np.linalg.solve(L, y)) return -0.5*y.T.dot(alpha) - np.sum(np.log(np.diag(L))) - 0.5*len(x)*np.log(2*np.pi) # 定义预测函数 def predict(x, y, x0, theta, sigma): k = gaussian_kernel(x, x, theta) + sigma**2 * np.eye(len(x)) k0 = gaussian_kernel(x, x0.reshape(1, -1), theta) k00 = gaussian_kernel(x0.reshape(1, -1), x0.reshape(1, -1), theta) try: L = np.linalg.cholesky(k) except np.linalg.LinAlgError: return np.nan, np.nan alpha = np.linalg.solve(L.T, np.linalg.solve(L, y)) mu = k0.T.dot(alpha) v = k00 - k0.T.dot(np.linalg.solve(L.T, np.linalg.solve(L, k0))) return mu, v # 生成随机数据 np.random.seed(666) X = np.random.uniform(-20, 20, size=(200, 10)) y = np.array([expensive_func(x) for x in X]) # 优化超参数 initial_params = [1, 1] bounds = [(1e-5, None), (1e-5, None)] res = minimize(lambda params: -log_likelihood(params, X, y), initial_params, bounds=bounds) theta, sigma = res.x # 在随机点上进行预测 x0 = np.random.uniform(-20, 20, size=(1, 10)) mu, v = predict(X, y, x0, theta, sigma) # 计算误差 exact_val = expensive_func(x0) error = (exact_val - mu)**2 print("预测误差:", error) print("预测方差:", v)注释一下
这段代码主要实现了使用高斯过程进行回归分析。其中定义了一个昂贵的函数 `expensive_func`,该函数实现了在给定输入的情况下进行昂贵计算的功能。然后定义了一个高斯核函数 `gaussian_kernel`,用于计算输入数据的协方差矩阵。接着定义了对数似然函数 `log_likelihood`,用于计算给定超参数情况下的对数似然值。最后定义了预测函数 `predict`,用于在给定超参数和输入数据的情况下进行预测。在代码中,使用了 `minimize` 函数对超参数进行优化,并使用随机数据进行了预测。最终输出预测误差和预测方差。
阅读全文