面试相关

随便记录一下面试中遇到的问题:

梯度下降和牛顿迭代的区别?为什么常用梯度下降?

**牛顿法是二阶收敛,梯度下降是一阶收敛,所以牛顿法就更快**。如果更通俗地说的话,比如你想找一条最短的路径走到一个盆地的最底部,梯度下降法每次只从你当前所处位置选一个坡度最大的方向走一步,牛顿法在选择方向时,不仅会考虑坡度是否够大,还会考虑你走了一步之后,坡度是否会变得更大。所以,可以说牛顿法比梯度下降法看得更远一点,能更快地走到最底部。

根据wiki上的解释,从几何上说,牛顿法就是用一个二次曲面去拟合你当前所处位置的局部曲面,而梯度下降法是用一个平面去拟合当前的局部曲面,通常情况下,二次曲面的拟合会比平面更好,所以牛顿法选择的下降路径会更符合真实的最优下降路径。

常用梯度下降的原因是牛顿迭代的计算时间复杂度太大了...

如果一个优化问题是n 维的,那么单轮梯度下降的复杂度是O(n) ,Quasi-Newton是O(n^2)

收敛速度和计算的时间复杂度是两回事,切记不要混淆。

拟牛顿法:拟牛顿法的本质思想是改善牛顿法每次需要求解复杂的Hessian矩阵的逆矩阵的缺陷,它使用正定矩阵来近似Hessian矩阵的逆,从而简化了运算的复杂度。

[Math] 常见的几种最优化方法

优化函数有哪些方法?非凸函数怎么办?在ml中如何求全局最优值?

梯度下降,牛顿法等数值计算方法(要求有二阶导数?

模拟退火,遗传算法等近似算法。

由于凸函数有一个很好的性质,即局部最优就是全局最优,所以求凸函数的最优解比较容易,梯度下降,贪心(比如爬山法)等局部算法都ok.

对于非凸函数的最优化比较困难,比较常见的有蒙特卡洛方法投点法,大概思想就是,投n次点,每次在该点附近用凸函数的优化方法求最值,最后取所有局部最值的max(min)

模拟退火应该也可以求解非凸函数? 毕竟喝醉的人可能走错路,陷入局部最优的时候有几率跳出。

什么是过拟合?如何防止过拟合?

我的理解,过拟合就是由于参数过多等原因导致训练出来的模型不够一般化,可能对当前训练用的数据集拟合得很好,但是换一个数据集就不能很好的拟合。

防止过拟合主要有几种方法:L1,L2,dropout,Early stopping,数据集扩增。

L1,L2都是正则化方法,通过在代价函数上添加一个关于features的惩罚项,使得每一个features尽可能小,从而降低每个features对cost的贡献程度。

dropout是指在深度学习网络的训练过程中,对于神经网络单元,按照一定的概率将其暂时从网络中丢弃。

dropout有效的原因没有统一结论(?

Early stopping便是一种迭代次数截断的方法来防止过拟合的方法,即在模型对训练数据集迭代收敛之前(**如果可以认为loss不会再减少了)**停止迭代来防止过拟合。

通俗得讲,数据机扩增即需要得到更多的符合要求的数据,即和已有的数据是独立同分布的,或者近似独立同分布的。一般有以下方法:

  * 从数据源头采集更多数据
  * 复制原有数据并加上随机噪声
  * 重采样
  * 根据当前数据集估计数据分布参数,使用该分布产生更多数据等

L1,L2规范化有什么区别?

核心:L2对大数,对异常值更敏感!

L1:计算绝对值之和,用以产生稀疏性,因为它是L0范式的一个最优凸近似,容易优化求解 L2:计算平方和再开根号,L2范数更多是防止过拟合,并且让优化求解变得稳定很快速(这是因为加入了L2范式之后,满足了强凸)。

L1 nrom几乎没有比L2 norm表现好的时候,优先使用L2 norm是比较好的选择。

特征值和奇异值的关系?

...?

有哪些旋转不变性(计算机视觉)

...?

逻辑回归和svm的关系?

内核通信(那是啥

如何改变一个常量的值(不能去除常量属性

#define定义的常量是真正的常量(保存在常量区),而const却是由编译器判断实现的常量,是一个假常量。const常量本质上还是一个变量,只不过C++中提出的const机制在编译层面上对const常量提供了写保护,是为了防止意外修改。

答案:volatile 关键字

volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。声明时语法:int volatile vInt; 当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。例如:

#include <stdio.h>  
int main()  
{  
    const volatile int i = 10;  
    int* pi = (int*)(&i);  
    *pi = 100;  
    printf("*pi: %d\n",*pi);  
    printf("i: %d\n",i);  
    printf("pi: %p\n",pi);  
    printf("&i: %p\n", &i);  
    return 0;  
}

智能指针?

智能指针的出现实际上就是为了可以方便的控制对象的生命期,在智能指针中,一个对象什么时候和在什么条件下要被析构或者是删除是受智能指针本身决定的,用户并不需要管理。

vector内存增长机制,可不可以手动减小容量?

可以减小,但是不能减小到任意值,只能减小到大于等于当前元素个数的最小的2的幂(?

vector(v).swap(v); // 清除v而且最小化它的容量

levelDB代码中让你印象深刻的部分(不记得了orz