1. 程式人生 > >梯度下降&模擬退火

梯度下降&模擬退火

scan 隨機梯度 alpha 隨機選擇 梯度下降法 amp 分享 bzoj3 內容

吳恩達老師的機器學習公開課的第二課主要講了隨機梯度下降算法,我記錄了一些要點並寫了一點自己的想法於此。

技術分享

以上便是第二節課的核心內容。

另外的內容還有隨機梯度下降法。思想是很平凡的,當數據較多的時候隨機選擇數據進行梯度下降,以精度換速度。

梯度下降法似乎並不能處理局部最優的問題。吳恩達老師在課上給的解釋是實際中大部分函數都是碗狀的,無需考慮局部最優問題。

梯度下降很容易讓人聯想到模擬退火算法。

這裏有模擬退火算法的一道典型例題:bzoj3580 http://www.lydsy.com/JudgeOnline/problem.php?id=3680

題意抽象後為給n個點的坐標(x,y)與權值w,找點ans使得技術分享

最小。

模擬退火算法用“醉鬼”思想嘗試跳出局部最優問題。

#include<cstdio>
#include<cmath>
#include<cstdlib>
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const double eps=1e-8;
const double T_min=1e-8;
const double PI=acos(-1.0);
const double step=0.99;
const int MAXN=10010;
double tot;
int n;
struct Point { double x,y,w; Point() {} Point(double xx,double yy) {x=xx;y=yy;} Point operator -(const Point &b)const { return Point(x-b.x,y-b.y); } Point operator +(const Point &b)const { return Point(x+b.x,y+b.y); } double operator *(const
Point &b)const { return x*b.x+y*b.y; } }p[MAXN]; Point now,ans; double dist(Point a,Point b) { return sqrt((a-b)*(a-b)); } double random01() { return (rand()%1000+1)/1000.0; } double fx(Point x) { double res=0.0; rep(i,1,n) res+=dist(x,p[i])*p[i].w; if(res<tot) {tot=res;ans=x;} return res; } int main() { srand(2333); //freopen("in.txt","r",stdin); int a,b,w,dif; tot=1e18; scanf("%d",&n); rep(i,1,n) { scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].w); now=now+p[i]; } now.x/=n;now.y/=n; double T=100000.0,alpha; while(T>T_min) { alpha=2.0*PI*random01(); Point tmp(now.x+T*cos(alpha),now.y+T*sin(alpha)); dif=fx(now)-fx(tmp); if(dif>=0||exp(dif/T)>random01()) now=tmp; T*=step; } T=0.001; rep(i,1,1000) { alpha=2.0*PI*random01(); Point tmp(ans.x+ T*cos(alpha)*random01(),ans.y+T*sin(alpha)*random01()); fx(tmp); } printf("%.3f %.3f\n",ans.x,ans.y); return 0; }

梯度下降&模擬退火