我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛
注:本系列文章以虚构的兔子世界为素材,穿插悬疑侦探。博君一笑,请勿当真。如有雷同,实属巧合~
书接上回。
突突和达达还是决定赴约,但出于安全考虑,这次它们没有带上小小。
两兔再次来到密林中,上次的兔子热情地欢迎了它们。
兔子问它们是否已经算出了结果,达达拿出了预先画好的三角图。(图片有点大,这里就不放出来了),只见最后一行的内容是:
[1,19,171,969,3876,11628,27132,50388,75582,92378,92378,75582,50388,27132,11628,3876,969,171,19,1]
对面的兔子点点头,它说道:“之前我提到的快捷办法————”
神秘黑箱登场
只见它边说边将桌上的一个矩形大黑盖掀开成两半,上半部分的屏幕突然发出了亮光。在突突和达达惊异的目光中,它的手指在下半部分的一排排列整齐的按钮中噼噼啪啪一顿狂敲,或者说像在飞舞和生花,而它说这是在写代码
。
最后,屏幕中输出了完整的杨辉三角前20行序列。
对面的兔子表示,这个黑箱很神奇,它能帮助解决很多问题,做很多决策。
因为兔子的本名中有“湘”字,又有一个大黑箱,突突和达达就把它记作“黑箱兔”了。
这时达达发问,“那这个箱子能告诉我,如果现在要在这个村子里设一个医馆,要建在哪里才能尽可能照顾到所有家庭呢?”
说着,它指了指黑箱兔屋子里墙上的地图。
医馆的最佳位置
黑箱兔眉毛一挑,“这个问题有点意思。”
只见它以地图的左下角为原点(0,0),标记了各个村民家的位置并记在纸上,随后,它编写了一段代码,并将这些数据输入黑箱。屏幕上显示了一个坐标。
三兔按照坐标找到了图上的地点,发现果然是兼顾各处。达达不由感叹:“妙啊!”
“不过,” 黑箱兔补充道:“虽然它确实很有用,但目前而言它于我们而言却还是一个黑箱。我们知道给它输入,它会有输出。但我们却不清楚它为什么会这样输出,背后的机制又是什么。对这个生成结果的程序
是这样,对这个黑箱本身也是这样。”
(作者注:在现实世界中,我们大多数人对计算机以及大火的机器ML、DL的真正了解又有多少呢?直到现在,后者的领域中的大多数东西也还是黑箱)
黑箱兔扭过头,看向达达和突突,“我最近在研究这个机器的底层———操作系统
,你们想一起来吗?”
达达和突突面面相觑。
本期总结及下期看点
突突和达达终于明白了密林中的兔子被避讳的原因。原来,是因为它们拥有一股神秘力量————黑箱。而其他兔子不懂,觉得它们很高深很可怕罢了。兔子们对自己不懂的事物总是又畏惧又抗拒。
那么,突突和达达是否会加入黑箱兔呢?它们又能否搞清其中的玄机?黑箱兔所说的操作系统
又该怎么理解呢?
欲知后事如何,请听下回分解!
附录
杨辉三角
详情参见百度百科 杨辉三角
杨辉三角是中国古代数学的杰出研究成果之一,它把二项式系数图形化,把组合数内在的一些代数性质直观地从图形中体现出来,是一种离散型的数与形的结合.
代码实现
以下代码借助杨辉三角的数学性质:
第 n 行的第 i 个数等于第 n−1 行的第 i−1 个数和第 i个数之和
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> list=new ArrayList<List<Integer>>();
for(int i=0;i<numRows;i++){
List<Integer> row=new ArrayList<>();
for(int j=0;j<=i;j++){
if(j==0||j==i) row.add(1);
else row.add(list.get(i-1).get(j-1)+list.get(i-1).get(j));
}
list.add(row);
}
return list;
}
}
梯度下降法
上文情形中用到了 梯度下降法
。
这是一种最优化算法,常用于机器学习和人工智能当中用来递归地逼近最小偏差模型。 所谓的“梯度”,就是函数的某个点在某时刻的斜率;求梯度,就是对函数求导。
梯度下降法服务于具体的应用场景。 以下是上文提到的场景的代码的具体实现。
代码实现
该题的梯度下降的手写版代码如下:(我用Java写算法题比较多,以下代码参考官解)
class Solution {
public double getMinDistSum(int[][] positions) {
double eps = 1e-7;
double alpha = 1;
double decay = 1e-3;
int n=positions.length;
int batchsize=n;
double x=0,y=0;
for(int [] pos:positions){
x+=pos[0];
y+=pos[1];
}
x/=n;
y/=n;
while(true){
shuffle(positions);
double xPre=x;
double yPre=y;
for(int i=0;i<n;i+=batchsize){
int j=Math.min(n,i+batchsize);
//求导
double dx=0,dy=0;
for(int k=i;k<j;k++){
int [] pos=positions[k];
dx+=(x-pos[0])/(Math.sqrt((x-pos[0])*(x-pos[0])+(y-pos[1])*(y-pos[1]))+eps);
dy+=(y-pos[1])/(Math.sqrt((x -pos[0])*(x-pos[0])+(y-pos[1])*(y-pos[1]))+eps);
}
x-=alpha*dx;
y-=alpha*dy;
alpha*=(1.0-decay);
}
if (Math.sqrt((x-xPre)*(x-xPre)+(y-yPre)*(y-yPre))<eps) {
break;
}
}
return getDistance(x,y,positions);
}
public double getDistance(double xc,double yc,int [][] positions){
double res=0;
for(int [] pos:positions){
int x=pos[0];
int y=pos[1];
res+=Math.sqrt((xc-x)*(xc-x)+(yc-y)*(yc-y));
}
return res;
}
public void shuffle(int[][] positions){
int n=positions.length;
Random r=new Random();
for(int i=0;i<n;i++){
int ran=r.nextInt(n);
int x=positions[i][0];
int y=positions[i][1];
positions[i][0]=positions[ran][0];
positions[i][1]=positions[ran][1];
positions[ran][0]=x;
positions[ran][1]=y;
}
}
}
- 梯度下降法是机器学习和深度学习领域中一个基本思想。一般实际应用中不需要自己实现这个过程。所以上述的代码一般不会出现在工程应用中,而更多出现在相关岗位的笔试面试考察中。
- 截至目前,用于搞机器学习和深度学习的代码语言主要是Python。