借鉴了两处:https://blog.csdn.net/dpengwang/article/details/99092278
https://leetcode-cn.com/problems/sqrtx/solution/x-de-ping-fang-gen-by-leetcode-solution/
https://zhuanlan.zhihu.com/p/46536960
梯度下降法
牛顿法
代码
import math
import random
import matplotlib.pyplot as plt
def gradient_descent(n):
x = float(random.randint(1, 100))
array = []
while abs(x ** 2 - n) > 0.0001:
x = x - 0.00001 * 4 * x * (x ** 2 - n)
array.append(x)
return array
def Newton(n):
array = []
x = float(random.randint(1, 100))
while abs(x ** 2 - n) > 0.000000001:
x = x - (x ** 2 - n) / (2 * x)
array.append(x)
return array
array1 = gradient_descent(10)
array2 = Newton(10)
x1 = range(len(array1))
x2 = range(len(array2))
fig, axs = plt.subplots(2)
axs[0].plot(x1, array1, 1, color='r')
axs[0].set_title('gradient descent')
axs[1].plot(x2, array2, 2, color='b')
axs[1].set_title('Newton method')
plt.show()
print(math.sqrt(10), array1[-1])
print(math.sqrt(10), array2[-1])
result
二分法
class Solution {
public:
int mySqrt(int x) {
int l = 0, r = x, ans = -1;
while (l <= r) {
int mid = l + (r - l) / 2;
if ((long long)mid * mid <= x) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
return ans;
}
};
或者
class Solution {
public:
int mySqrt(int x) {
int lo = 0;
int hi = x;
if(x==0) return 0;
if(x==1) return 1;
while((lo+1)!=hi){
int mid = lo + (hi-lo)/2;
if ((long long)mid*mid <= x){
lo = mid;
}else{
hi = mid;
}
}
return lo;
}
};
比较梯度下降和牛顿法/拟牛顿法
优点:牛顿法下降速度更快,得到的解更优。凸优化且距离最优点较近时,牛顿法明显优于梯度下降法。
缺点:牛顿法是一种迭代算法,每一步都需要求解目标函数的Hessian矩阵的逆矩阵,计算比较复杂。
牛顿法收敛速度为二阶,对于正定二次函数一步迭代即达最优解。
牛顿法是局部收敛的,当初始点选择不当时,往往导致不收敛;
二阶海塞矩阵必须可逆,否则算法进行困难。
所以深度学习中:
往往采用梯度下降法作为优化算子,而很少采用牛顿法,主要原因有以下几点:
神经网络通常是非凸的,这种情况下,牛顿法的收敛性难以保证;
2. 即使是凸优化,只有在迭代点离全局最优很近时,牛顿法才会体现出收敛快的优势;
- 可能被鞍点吸引。