机器学习数学基础
总共可以分为五块:高数、线代、概率论与数理统计(考研三大块)、随机过程和mcmc抽样(最后两个严格意义上也属于数理统计的内容)。
本人是应统专业的,后面的就先鸽一下,前面高数线代的内容在这里先补充一下,其实大部分考研也学过,这里就展示下思维导图吧。
高等数学
线性代数
随机牛顿法及其代码实现
Rosenbrock函数
Rosenbrock函数是一个用来测试最优化算法性能的非凸函数,由Howard Harry Rosenbrock在1960年提出,因其函数形状类似香蕉,故别名为香蕉函数:
f ( x , y ) = ( a − x 1 ) 2 + b ( x 2 − x 1 2 ) 2 f(x, y) = (a - x_1)^2 + b(x_2 - x_1^2)^2 f(x,y)=(a−x1)2+b(x2−x12)2
其中 x = ( x 1 , x 2 ) T ∈ R 2 ; a , b ∈ R \bm{x} = (x_1 , x_2)^T \in R^2 \; ; a,b \in R x=(x1,x2)T∈R2;a,b∈R
用python实现该函数:
# 导入第三方库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import time
from mpl_toolkits.mplot3d import Axes3D
# Rosenbrock函数
def function(x1, x2, a, b):
return np.square(a - x1) + b * np.square(x2 - np.square(x1))
# 绘制函数图像
def plot_function(a, b):
# 网格数据和函数值
x = np.arange(-100, 100, 0.1)
y = np.arange(-100, 100, 0.1)
x, y = np.meshgrid(x, y)
z = function(x, y, a, b)
# 绘制3d图像
fig = plt.figure()
ax = plt.axes(projection='3d')
# 函数图像和找到的最小值点
ax.plot_surface(x, y, z, alpha=0.3, cmap='winter')
# 设定显示范围
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# 显示a, b的值
plt.title('a= %.2f , b= %.2f ' % (a, b))
其图像特点在于当 b b b 符号变为负数或 a = 0 a=0 a=0 时,图像形状就会发生改变:
随机牛顿法
随机牛顿法是对牛顿法的改进,它利用多次生成的随机值作为牛顿法的初始值,进行迭代后寻找多个牛顿法结果的最优解,有些类似kmeans++对kmeans的优化。
以求解上面的Rosenbrock函数为例,用python实现牛顿法求其最值:
# 计算函数梯度
def gradient(x1, x2, a, b):
# 对x1、x2求一阶偏导
delta_x1 = 4*b*x1**3 - 4*b*x1*x2 + 2*x1 - 2*a
delta_x2 = -2*b*x1**2 + 2*b*x2
return np.array([delta_x1, delta_x2]).reshape(-1, 1)
# 计算函数海森矩阵
def Hessian(x1, x2, a, b):
# 求二阶偏导
delta_x1x1 = 12*b*x1**2 - 4*b*x2 + 2
delta_x1x2 = -4*b*x1
delta_x2x2 = 2*b
return np.array([[delta_x1x1, delta_x1x2], [delta_x1x2, delta_x2x2]])
# 牛顿法求解函数最小值
def snt(x1, x2, z, newton_times, alpha):
# 随机初始化
rand_init = np.random.randint(0, z.shape[0])
x1_init, x2_init, z_init = x1[rand_init], x2[rand_init], z[rand_init]
x_0 = np.array([x1_init, x2_init]).reshape(-1, 1)
# 进行迭代
for i in range(newton_times):
# 计算海森矩阵的逆
H_inv = np.linalg.inv(Hessian(x1_init, x2_init, a, b))
# 计算梯度
grad = gradient(x1_init, x2_init, a, b)
# 更新参数
x_i = x_0 - alpha * np.matmul(H_inv, grad)
x_0 = x_i
x1_init = x_0[0, 0]
x2_init = x_0[1, 0]
# 返回终解
return x_0
随机牛顿求解Rosenbrock函数最小值
随机牛顿中随机优化次数(运行牛顿法的次数)设置为10次,牛顿法的步长设置为0.2,迭代次数设置为1000次,实验代码如下:
# 绘制函数与最值
def plot_data(min_x1, min_x2, min_z, a, b):
x = np.arange(-100, 100, 0.1)
y = np.arange(-100, 100, 0.1)
x, y = np.meshgrid(x, y)
# 函数值
z = function(x, y, a, b)
# 绘制3d图像
fig = plt.figure()
ax = plt.axes(projection='3d')
# 函数图像和找到的最值点
ax.plot_surface(x, y, z, alpha=0.3, cmap='winter')
ax.scatter(min_x1, min_x2, min_z, c='r')
# 设定显示范围
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# 显示a, b的值
plt.title('a= %.2f , b= %.2f ' % (a, b))
# Rosenbrock函数最值求解
class Rosenbrock():
def __init__(self):
self.answers = []
self.min_answer_z = []
# 开始
def start(self):
# 计算对应函数值
z = function(x1, x2, a, b)
# 算法运行开始时间
start_time = time.time()
# 记录指定次数随机牛顿法的最终解
for i in range(times):
answer = snt(x1, x2, z, newton_times, alpha)
self.answers.append(answer)
min_answer = np.array(self.answers)
# 记录指定次数随机牛顿法的对应的函数值
for i in range(times):
self.min_answer_z.append(function(min_answer[i, 0, 0], min_answer[i, 1, 0], a, b))
# 最终优化后的解
optimal_z = np.min(np.array(self.min_answer_z))
optimal_z_index = np.argmin(np.array(self.min_answer_z))
optimal_x1, optimal_x2 = min_answer[optimal_z_index, 0, 0], min_answer[optimal_z_index, 1, 0]
# 算法运行结束时间
end_time = time.time()
# 算法执行时间
running_time = end_time - start_time
print('函数最小值%.2f在(%.2f, %.2f)处取得' % (optimal_z, optimal_x1, optimal_x2))
print('优化的时间:%.2f秒!' % running_time)
plot_data(optimal_x1, optimal_x2, optimal_z, a, b)
# 开始执行算法
if __name__ == '__main__':
# 函数与优化参数的输入
a = float(input("请输入a的值:"))
b = float(input("请输入b的值:"))
alpha = float(input("请输入随机牛顿法的步长:"))
newton_times = int(input("请输入随机牛顿法的迭代次数:"))
times = int(input("请输入需要随机优化的次数:"))
x1 = np.arange(-100, 100, 0.0001)
x2 = np.arange(-100, 100, 0.0001)
Rosenbrock().start()
结果如下图所示: