提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
面试问题准备
一、数据结构
1.sort()函数原理
sort(begin,begin+n,cmp)
//快速排序+插入排序+推排序
//复杂度:n*log2n
用于:数组、链表、向量排序
系统会自动选择合适的排序方法-根据数据类型和数据量;
每次排序不只选择一种方法;
比如:一个数据量较大的数组排序,开始采用快速排序,分段递归,分段之后每一段的数据量达到一个较小值后就不继续往下递归,而是选择插入排序,如果递归的太深,会选择推排序。
2.priority_queue优先队列
自定义排序方式
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> q(cmp);
//decltype(cmp):实现自定义排序方式——>默认第一个关键字降/升序排列
bool cmp(pair<int, int>& m, pair<int, int>& n) {
return m.second > n.second;//按照第二个关键字降序排列
}
auto cmp=[&nums1, &nums2](const pair<int, int> & a, const pair<int, int> & b) {
return nums1[a.first] + nums2[a.second] > nums1[b.first] + nums2[b.second];
};//按照第一二关键字nums和,降序排列
priority_queue<pii,vector<pii>,decltype(cmp)> heap(cmp);
//heap(cmp)必须加cmp,已尝试,不加报错
//因为auto是lambda特殊的class,没有构造函数,heap内部实现比较要通过lambda的copy使用实例化的lambda对象,copy通过构造heap函数的时候传入这个lambda对象来实现;如果使用struct或class定义则不需要heap(cmp),直接heap即可
3.排序算法复杂度分析
二分查找 O(n)=log2(n)
比较一下,两种不同的边界写法
int n=nums.size();
int l=0,r=n-1,res=n;
while(l<=r){//1111111
int mid=(l+r)/2;//111111
if(target<=nums[mid]){//111111
res=mid;//111111
r=mid-1;
}
else{
l=mid+1;//11111对应mid=l+r
}
}
return res;
while(l<r){//111111
int mid=(l+r+1)/2;//11111
if(target<matrix[mid][0]){//<11111
r=mid-1;
}
else{
l=mid;//11111对应mid=l+r+1
}
res=l;//111111比较每行的左边界,查找边界不大于目标的行
}//源于二维矩阵查找所在行
4.背包问题
代码复习
//0-1背包问题
m[i][j]=max(m[i-1][j],m[i-1][j-wi]+vi)
//背包里放到第i个物品的最大总价值为m[i][j],j为剩余可容纳重量
for(int i=1;i<=n;i++){
for(int j=1;j<=c;j++){
if(j<w[i]) f[i][j]=f[i-1][j];
else f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
}
}
for(int i=1;i<=n;i++){
cin>>w>>v;
for(int j=c;j>=w;j--){
f[j]=max(f[j],f[j-w]+v);
}
}
0-1背包若使用一维dp数组,遍历物品放外层,遍历背包target放内层,target倒着遍历
完全背包,遍历物品放外层,遍历背包target放内层,target正着遍历
考虑组合:外商品,内背包,(求装满背包)递推公式:dp[j] += dp[j - nums[i]];
考虑排列:外背包,内商品
做题步骤:
1.判断问题是哪种背包类型(0-1或完全
2.判断问题是组合/排列/其他
3.确定f[j]
的意义——直接表示问题所要求的答案
4.确定递推公式 max/min/其他 f[j]=……
5.动态规划
动规五步曲:
1.确定f[i][j]
数组及其下标含义
2.确定递推公式
3.数组初始化
4.确定遍历顺序
5.举例推导f数组
贪心有bug一般就会使用dp
6.回溯
创建函数backtracking
对一个集合可重复使用,函数形参添加start结点限制
void backtracking(vector<int> candidates,int target,int start)
对于多个组合互相之间无关,则不需添加这个循环限制
void backtracking(vector<int> candidates,int target)
做题步骤:
1.确定最后的返回类型、中间递归的暂存类型,进行相关定义
2.构造backtracking()
函数,同时主函数写调用,类别确定形参
3.回溯函数里创建for循环
4.确定循环边界条件
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for(int i=0/strat;i<n;i++){
path.push_back(xxxx[i]);//处理结点
backtracking(xxxx,xxxx);//递归
path.pop_back();//回溯
}
}
7.树
两个序列建树
做题步骤:
1.数组大小为0,空结点
2.找出后序最后一个元素/先序第一个元素,切割中序
3.切割后序/先序
4.递归
树结点的数据结构:
typedef struct treeNode{
int val;
treeNode *left,*right,*father;
}treeNode;
8.C++内置函数
islower(char c) 是否为小写字母
isupper(char c) 是否为大写字母
isdigit(char c) 是否为数字
isalpha(char c) 是否为字母
isalnum(char c) 是否为字母或者数字
toupper(char c) 字母小转大
tolower(char c) 字母大转小
9.双指针问题
都是从两端往中间移动
int n=height.size();
int i=0,j=n-1;
while(i<j){
}
10.vector
int minPathSum(vector<vector<int>>& grid) {
int n=grid.size();
int m=grid[0].size();
vector<vector<int>> f(n,vector<int>(m));//初始化方法!!!
vector<int> vec(nums.begin(),nums.begin()+k);
k=1的话,vec只有nums[0]一个数,而不是[0,1]两个数
求数组最大最小值:
#include< algorithm >
//vector容器
int max_num = *max_element(nums.begin(), nums.end()); //获取最大值
int min_num = *min_element(nums.begin(), nums.end());//获取最小值
//普通数组
int max_num = *max_element(nums, nums + 8);
int min_num = *min_element(nums, nums + 8);
11.深搜三部曲
1.确认递归函数、参数
2.确定终止条件
3.处理目前搜索结点出发路径
others.其他
const:对定义的变量必须赋值,且赋值后不可修改
atoi():字符串变数字
*是指针;&是引用(修改变量减少内存变化
二、机器学习
1.偏差bias和方差variable之间的均衡
建模时不希望模型同时有高偏差和高方差
bias是欠拟合的表现,反映样本输出与真实值之间的误差,即模型的精确度;variable是过拟合的表现,反映样本输出与期望值之间的误差,即模型的稳定性;方差是偏差平方和的平均数
通常在基础数据集上添加偏差、误差和噪声引起的不可约误差,分散算法的学习误差,模型变复杂意味着在失去一些偏差而获得一些方差,通过这种方式实现均衡。
2.监督学习和非监督学习的不同
最大的不同在于数据集是否有标签
3.KNN和K-means的不同
KNN即k近邻算法,是监督学习分类算法;K-means聚类,是无监督学习聚类算法。
K-means k的选取原则:
肘部法则
连续迭代k=1到k=n,计算每个k值对应的簇内平方和(WCSS)-每个样本到簇内中心点的距离偏差之和,当k=1时,WCSS具有最高值,但随着k值的增加,WCSS值开始减小
WCSS的计算,比如选择欧式距离:
Distortion = 1/n * Σ(distance(point, centroid)^2)
绘制k-WCSS关系图,取拐点对应的k值,我们选择k的最优解,是因为,在图中,当k值小于最优解是,k每增大1,距离和会大幅下降;k值大于最优解时,k每增加1,距离和变化很小,基于这样的经验性准则,我们应该选取曲线肘部为最优值。
4.ROC曲线原理
TPR真正例率=TP/P=TP/(TP+FN) (第一列
FPR假正例率=FP/N=FP(FP+TN) (第二列
精确度/查准率precision:TP/(TP+FP) (第一行
正确预测为正例的结果个数占所有预测为正例结果个数的百分比;又称阳性预测值
召回率/查全率recall:TP/(TP+FN) (第一列
正确预测为正例的结果个数占真实正例总个数的百分比;又称真阳性率
行是预测,列是真实
ROC曲线:
从一般情况下泛化性能的好坏的角度出发研究学习器的泛化性能;
纵轴为TPR,横轴为FPR,
将测试样本进行排序,最可能是正例的放在前面,最不可能的放在后面;
连接每一个样本的(TPR,FPR)点
兼顾正例和负例的权衡
P-R曲线:
纵轴为precision,横轴为recall
连接每一个样本的(precision,recall)点
两个指标都聚焦于正例
P-R曲线里面部分的面积为AUC,其值越接近于1越好;表示为不同召回值的情况下,所有精度的平均值,即mAP。
5.贝叶斯定理
给出了已知先验知识下,事件的后验概率
可以依靠与事物特定本质相关的事件出现的概率来判断其本质属性的概率
6.损失函数
度量预测值与实际值之间的误差
0-1损失函数:预测值与真实值有落差,损失函数值为1,无落差值为0
绝对损失函数:预测值与实际值的差的绝对值
平方损失函数:差的平方——便于求导
对数损失函数:log——方便用极大似然估计求极值
方差
标准差/均方差
MSE:均方误差,误差平方和的平均值
7.经验风险最小化
经验风险最小化:经验风险最小的模型是最优模型,极大似然估计;最小化训练集上的期望损失将机器学习转化为优化问题;训练集上的平均损失称为经验风险/经验损失,最小化平均训练误差的过程称为经验风险最小化;
结构风险最小化=正则化=经验风险+正则项
期望风险:输入输出遵循联合概率分布,损失函数的期望称为期望损失/风险函数
8.核函数
将原始空间中的向量作为输入向量,并返回特征空间中的向量的点积的函数
三、深度学习
1.pytorch框架
CUDA、NumPy、scipy、matplotlib、OpenCV、sklearn
2.卷积核
卷积核大小不同,对应输入图像的感受野不一样;
较大的卷积核可以捕获更宽泛的特征,较小的卷积核更关注细微的信息。小核偏向于提取小物体,大核偏向于提取大物体。
1.多层小卷积核堆叠可以和大卷积核有一样的感受野,但小卷积核的参数和计算量更少(更经济)
2.多层小卷积核堆叠,相较于大卷积核,可以引入更多非线性——使用更多的激活函数(效果更好)
卷积和池化的区别
卷积是为了提取图像特征;
目标图像和滤波器做乘积和;
池化简言之,区域平均或最大
是为了减少卷积层提取的特征个数——去除无用特征,增加特征的鲁棒性、增加模型的泛化性;或者说降维——简化模型;
简单的最大值、最小值、平均值操作;
图像相邻像素倾向于有相同的值,这意味着卷积层的输出包含的大部分信息是冗余的,池化层降维-降低输出元素数量,能解决这个冗余问题。
3.反向传播(bp
通过误差传播、参数更新两个环节循环迭代形成;
神经网络的训练过程中,前向传播和反向传播交替进行;
前向传播通过训练数据和权重参数计算输出结果;
反向传播通过导数链式法则计算损失函数对各参数的梯度,并根据梯度进行参数的更新。
神经网络的BP就是通过链式法则求出损失函数L对所有参数梯度的过程。
除非用随机梯度下降,否则每次用以训练的样本都是整个batch计算的,损失函数L则是整个batch中样本得到损失的均值。
4.CNN全连接层
最后激活函数的输出为335,那么就用335的滤波器对这个输出进行卷积,得到全连接层一个神经元的输出,这一个神经元对应的就是一个值。
要得到114096的全连接层,就是用4096个这样的滤波器对输出进行卷积。
实现功能:把特征整合在一起,大大减少特征位置对分类带来的影响。——对于电脑来说,特征值相同,但是特征位置不同,也可能对分类结果造成影响。
因为空间结构特性被忽略了,所以全连接层不适合用来在不同位置上找目标,比如分割!!!所以语义分割要用FCN——把全连接层也换成卷积层。
只用一层全连接层,有时候没办法解决非线性问题,如果有两层及以上,就能够很好的解决了。
第一个全连接层,将前面卷积层不同大小的感受野提取到的抽象信息,映射到更大的空间中,增加模型的表征能力。
第二个全连接层,更多的是为了匹配物体检测网络的输出尺度。两次线性变换得到需要的维数。
5. 激活函数
sigmoid:只输出正数,靠近0的输出变化率大,容易造成梯度消失,输入0均值但输出不是0均值,指数运算计算量大,反向传播求误差梯度时求导涉及除法和指数运算;常见于全连接层;
tanh:输出可以是负数,同样靠近0的变化率大
relu:输入只能是正数,(输入是图片格式常用),使一部分神经元的输出为0,造成网络的稀疏性,减少参数相互依存关系,缓解过拟合;导数只有0和1,神经元的梯度始终为1,不会梯度传播时变小;常见于卷积层**;计算简单快速**;
maxout:参数较多,本质在输出结果的基础上又增加一层;
softmax:将多分类的输出值转换为范围0-1,和为1的概率分布;不再唯一确定某个最大值,而是为每个输出分类的结果都赋予一个概率值,表示属于每个类别的可能性;(指数形式)
作用:提高鲁棒性(参数波动时维持某些性能的特性),非线性表达能力,缓解梯度消失问题,将特征图映射到新的特征空间从而更有利于训练,加速模型收敛
梯度爆炸的判断:损失变化显著或变为NaN
6.MLP多层感知机
也叫人工神经网络,
典型三层:输入层、隐层、输出层;不用层之间全连接
神经网络三个基本要素:权重、偏置、激活函数
7.归一化和标准化
归一化:数值归一,确保数据处于同一量级,丢失数据分布信息,保留权值;
适用于不涉及距离度量、协方差计算、非正态分布时;
(需要归一化场景:逻辑回归、SVM、神经网络、SGD)
先使用最小值平移,后使用最值差缩放;
(不需要归一化场景:0/1取值的特征、决策树——树模型是阶跃的阶跃点不可导、最小二乘法——抛物线下降速度快)
常用归一化:L1范式:绝对值相加;L2范式:欧几里得之和
标准化:数据分布归一,丢失权重,保留数据分布;
适用于聚类、分类算法——需要使用距离来度量;
先使用均值μ平移,再使用标准差σ缩放;
相同点:归一化包含标准化,都是进行特征提取,方便数据比较,都是为了缩小范围便于后续数据处理;
作用:加快梯度下降、损失函数收敛;提升模型精度、分类准确率;防止梯度爆炸;
8.生成对抗网络
由生成模型和判别模型,对抗博弈直至达到平衡完成训练,生成模型要以假乱真,判别模型要辨别真假
9.tensorflow的计算图
也叫数据流图,用结点和线组成的有向图来描述数学计算;结点表示施加的操作或输入输出,线表示多维数据数组的传输;
10.神经网络的变种
BP神经网络(误差反向传播)
RNN循环神经网络——自然语言处理
DNN深度神经网络——传统全连接网络
CNN卷积神经网络——图像识别
LSTM时间递归神经网络——语音识别
MLP多层感知机
11.调参
cnn调参主要在优化函数:SGD(随机梯度下降)——有机会跳出局部极小继续搜索、Adam优化器
调参效果不好要考虑的因素:合适的损失函数,合适的batch-size,合适的激活函数,学习率(学习率小收敛慢、学习率大损失函数震荡),合适的优化算法,是否过拟合;
12.LSTM
使用两种激活函数sigmoid和tanh
sigmoid用在各种门上,1记住或者0忘掉;
tanh用在输出上,处理数据
13.RNN
解决梯度爆炸:使用梯度截断、改变激活函数、批量归一化
解决梯度弥散:改变随机初始化为有关联的矩阵初始化、或者relu代替sigmoid;
14.什么样的数据集不适合深度学习
1.数据集太小,样本不足,深度学习没有优势
2.数据集没有局部关联性;目前深度学习表现较好的领域是图像/语音/自然语言处理,图像像素组成物体、语音音位组合成单词、文本单词组合成句子;元素打乱会影响结果;
15.防止过拟合
dropout
L1/L2正则化,增加约束项
批量归一化
提前终止训练
数据增强、增加训练集数据
集成学习,多个模型集成,bagging
16.防止欠拟合
增加模型复杂度
减少正则化系数
增加特征数
17.全局平均池化GAP
代替全连接层,减少参数量、计算量,减少过拟合
18.非极大值抑制NMS
抑制不是极大值的元素,搜索局部极大值;
来去除重复的目标框,获得真正的目标框;
19.加快收敛、降低训练难度的方法
残差,学习率,优化器,预训练
20.残差块
网络深度增加,训练会变困难,
残差使:前向传播时,输入信号可以从任意低层直接传播到高层,解决网络退化问题;
反向传播时,更新的信号可以不经过中间任何权重矩阵的变换,直接传播到低层,缓解梯度弥散;
——残差使信息前后传播更顺畅;
21.批尺寸batch_size
随batch_size增大,内存利用率提高,但内存的容量可能撑不住,处理相同数据量的速度越快,跑完一次epoch(全数据集)所需的迭代次数减少,达到相同精度所需要的epoch数量越来越多,花费的时间增加,参数的修正变慢。
others.其他
有些数据不是线性分布的,用直线不能很好的拟合,所以引入非线性。
CNN的关键是卷积计算,完成特征提取,不同领域的机器学习都是通过特征进行建模来解决问题,用CNN可以解决不同领域的特征提取问题——基于局部连接、权值共享。
当不存在全局的的特征分布时,局部卷积更适合特征提取;
更深的网络更好:仅需要更少的参数就可以表达许多重要函数类;层数增加,困难分类问题的正确率更高;
正则化原理:在损失函数上加上某些限制缩小解空间;
fine-tuning:使用预训练好的网络做预训练模型,进行微调
anchor用来预设目标框,实现寻找图片中可能存在物体的区域;
学习率的选择:一是根据经验,一般设0.01-0.001
二是逐步增大学习率,画出学习率-损失函数曲线/准确率-损失函数曲线,找损失下降最快对应的学习率/准确率增长变平或锯齿状抖动时对应的学习率。
BN:批量归一化,本身是一个归一化网络;
可以选择比较大的初始学习率,具有快速收敛的特性,加速模型训练;具有提高网络泛化能力的特性,提升模型精度。
dropout:以特定概率随即让部分神经元失活(不参与训练),防止过拟合
L0:向量中非零元素的个数
L1:绝对值之和
L2:平方和开根号
python和c++
我更喜欢python,使用两种语言都进行过基础算法编程,感觉python语言更简洁;另外,我的项目接触的语言基本都是python,特别是作为解释性语言、在命令行不需编译直接就可以看到结果,互动更快速。
总结
best wishes.