面试笔记:面经-拼多多


一、自我介绍及印象最深项目

个人背景、项目经历、实习经历。
印象最深项目:SVM相关。


二、机器学习

2.1 SVM与LR的区别

  • LR是参数模型,SVM是非参数模型。
  • 从目标函数来看,区别在于LR采用的是logistical loss,SVM采用的是hinge loss。这两个损失函数的目的都是增加对分类影响较大的数据点的权重,减少与分类关系较小的数据点的权重。
  • SVM的处理方法是只考虑support vectors,也就是和分类最相关的少数点,去学习分类器。而LR通过非线性映射,大大减小了离分类平面较远的点的权重,相对提升了与分类最相关的数据点的权重。
  • LR相对来说模型更简单,好理解,特别是大规模线性分类时比较方便。而SVM的理解和优化相对来说复杂一些,SVM转化为对偶问题后,分类只需要计算与少数几个支持向量的距离,这个在进行复杂核函数计算时优势很明显,能够大大简化模型和计算。
  • LR能做的SVM能做,但可能在准确率上有问题,SVM能做的LR有的做不了。

2.2 SVM介绍、支持向量定义、SVM大致推导过程

SVM可以用于解决二分类或者多分类问题。SVM的目标是寻找一个最优化超平面在空间中分割两类数据,这个最优化超平面需要满足的条件是:离其最近的点到其的距离最大化,这些点被称为支持向量
推导过程:
在样本空间中,划分超平面可用 ω T + b = 0 \omega^T+b=0 表示,记为 ( ω , b ) (\omega,b) ,样本点 ( x i , y i ) (x_i,y_i) 到划分超平面的函数间隔为 γ i ^ = y i ( ω x i ) + b \hat{\gamma_i}=y_i(\omega\cdot x_i)+b ,几何间隔为: γ = γ ^ ω \gamma=\frac {\hat{\gamma}} {\begin{Vmatrix}\omega\end{Vmatrix}}
ω = 1 \begin{Vmatrix}\omega\end{Vmatrix}=1 ,可知函数间隔和几何间隔相等,若超平面参数 ( ω , b ) (\omega,b) 成比例的改变(超平面没有变),则函数间隔也是成比例的改变,而几何间隔不变。支持向量机的基本想法就是求解能够正确划分训练数据集并且几何间隔最大的分离超平面,表达为数学公式即为:
{ max ω , b γ ^ ω s . t . y i ( ω x i ) + b γ ^ i = 1 , 2 , . . . , N \begin{cases} \max\limits_{\omega,b}\frac {\hat{\gamma}} {\begin{Vmatrix}\omega\end{Vmatrix}} \\ s.t. \quad y_i(\omega\cdot x_i)+b\geq\hat{\gamma} \quad i=1,2,...,N \end{cases}
其实函数间隔 γ ^ \hat{\gamma} 的取值并不影响最优化问题的解,假设将 ω \omega b b 成倍的改变为 a ω a\omega a b ab ,那么函数间隔也会相应变成 a γ ^ a\hat{\gamma} ,函数间隔的对上面最优化问题的不等式没有影响,也对目标函数没有影响,因此为简便,取 γ ^ = 1 \hat{\gamma}=1 ,而且我们注意到最大化 1 ω \frac {1} {\begin{Vmatrix}\omega\end{Vmatrix}} 等价于最小化 1 2 ω 2 \frac {1}{2}\begin{Vmatrix}\omega\end{Vmatrix}^2 ,便可得到支持线性可分的支持向量机的最优化问题:
{ min ω , b    1 2 ω 2 s . t . y i ( ω x i ) + b 1 0 i = 1 , 2 , . . . , N \begin{cases} \min\limits_{\omega,b} \;\frac {1}{2}\begin{Vmatrix}\omega\end{Vmatrix}^2 \\ s.t. \quad y_i(\omega\cdot x_i)+b-1\geq0 \quad i=1,2,...,N \end{cases}
这是一个凸二次优化的问题,可以直接求解,但是为了简便应用拉格朗日对偶性,求解对偶问题
建立拉格朗日函数,引进拉格朗日乘子 α i 0 i = 1 , 2 , . . . , N \alpha_i\geq0,i=1,2,...,N ,定义拉格朗日函数:
L ( ω , b , α ) = 1 2 ω 2 i = 1 N α i y i ( ω x i + b ) + i = 1 N α i L(\omega,b,\alpha)=\frac {1}{2}\begin{Vmatrix}\omega\end{Vmatrix}^2-\sum_{i=1}^N\alpha_iy_i(\omega\cdot x_i+b)+\sum_{i=1}^N\alpha_i
根据原始问题的对偶性,原始问题的对偶性是极大极小问题,即 max α min ω , b L ( ω , b , α ) \max\limits_{\alpha}\min\limits_{\omega,b}L(\omega,b,\alpha)
首先求最小,令 L ( ω , b , α ) L(\omega,b,\alpha) 分别对 ω \omega b b 求导为零可得:
{ ω = i = 1 m α i y i x i 0 = i = 1 m α i y i \begin{cases} \omega=\sum_{i=1}^m\alpha_iy_ix_i \\ 0=\sum_{i=1}^m\alpha_iy_i \end{cases}
将其代入对偶问题,可得:
{ max α    i = 1 m α i 1 2 i = 1 m j = 1 m α i α j y i y j x i T x j s . t .        i = 1 m α i y i = 0 , α i 0 , i = 1 , 2 , . . . , m \begin{cases} \max\limits_{\alpha}\;\sum_{i=1}^m\alpha_i-\frac{1}{2}\sum_{i=1}^m\sum_{j=1}^m\alpha_i\alpha_jy_iy_jx_i^Tx_j \\ s.t. \;\;\;\sum_{i=1}^m\alpha_iy_i=0,\alpha_i\geq0,i=1,2,...,m \end{cases}
解出 α \alpha 之后,那么 ω \omega b b 也相应得到。 f ( x ) = ω T + b = i = 1 m α i y i x i T x + b f(x)=\omega^T+b=\sum_{i=1}^m\alpha_iy_ix_i^Tx+b
上式不等式约束的kkt条件:
{ α i 0 y i f ( x i ) 1 0 α i ( y i f ( x i ) 1 ) = 0 \begin{cases} \alpha_i\geq0 \\ y_if(x_i)-1\geq0 \\ \alpha_i(y_if(x_i)-1)=0 \end{cases}
对于任意训练样本 ( x i , y i ) (x_i,y_i) ,总有 α i = 0 \alpha_i=0 或者 y i f ( x i ) = 1 y_if(x_i)=1 ,也就是说最终与模型有关的的样本点都位于最大间隔的边界上,称之为支持向量,其余的样本点与模型无关。

2.3 L2正则介绍及作用

L2正则化是指权值向量 ω \omega 中各个元素的平方和然后再求平方根,通常表示为 ω 2 \begin{Vmatrix}\omega\end{Vmatrix}_2
L2正则化可以防止模型过拟合(overfitting)。

2.4 KMeans介绍及相关参数

KMeans算法流程:

  • 选择聚类的个数k(kmeans算法传递超参数的时候,只需设置最大的K值)。
  • 任意产生k个聚类,然后确定聚类中心,或者直接生成k个中心。
  • 对每个点确定其聚类中心点。
  • 再计算其聚类新中心。
  • 重复以上步骤直到满足收敛要求(通常就是确定的中心点不再改变)。

scikit-learn中KMeans类的主要参数有:

  • n_clusters:即k值,一般需要多试一些值以获得较好的聚类效果。k值好坏的评估标准在下面会讲。
  • max_iter:最大的迭代次数,一般如果是凸数据集的话可以不管这个值,如果数据集不是凸的,可能很难收敛,此时可以指定最大的迭代次数让算法可以及时退出循环。
  • n_init:用不同的初始化质心运行算法的次数。由于K-Means是结果受初始值影响的局部最优的迭代算法,因此需要多跑几次以选择一个较好的聚类效果,默认是10,一般不需要改。如果你的k值较大,则可以适当增大这个值。
  • init:即初始值选择的方式,可以为完全随机选择random,优化过的k-means++或者自己指定初始化的k个质心。一般建议使用默认的k-means++
  • algorithm:有autofull或者elkan三种选择。full就是我们传统的K-Means算法, 默认的auto则会根据数据值是否是稀疏的,来决定如何选择fullelkan。一般数据是稠密的,那么就是elkan,否则就是full。一般来说建议直接用默认的auto

三、场景题

快递分拣:数据获取、特征提取、模型选择、精确率判断。

3.1 数据获取

从各大平台获取,并做简单预处理类似空值处理等等。

3.2 特征提取

以省、市、区、街道等等作为标签,L1正则特征清洗。

3.3 模型选择

因为特征值存在缺失所以采用了决策树。

3.4 精确率判断

P = T P T P + F P P=\frac{TP}{TP+FP}

  • 真正例TP:是指模型将正类别样本正确地预测为正类别。
  • 真负例TN:是指模型将负类别样本正确地预测为负类别。
  • 假正例FP:是指模型将负类别样本错误地预测为正类别。
  • 假负例FN:是指模型将负类别样本正确地预测为负类别。

四、算法题(手撕)

4.1 链表的构造(Node类,LinkedList类以及add、delete方法)

class Node {
    Node next = null;
    int data;

    public Node(int data) {
        this.data = data;
    }
}

class LinkedList {
    Node head = null;

    public void addNode(int d) {
        Node newNode = new Node(d);
        if (head == null) {
            head = newNode;
            return;
        }
        Node temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = newNode;
    }

    public Boolean deleteNode(int index) {
        if (index < 1 || index > length()) {
            return false;
        }
        if (index == 1) {
            head = head.next;
            return true;
        }
        int i = 2;
        Node preNode = head;
        Node curNode = preNode.next;
        while (curNode != null) {
            if (i == index) {
                preNode.next = curNode.next;
                return true;
            }
            preNode = curNode;
            curNode = curNode.next;
            i++;
        }
        return true;
    }

    public int length() {
        int length = 0;
        Node temp = head;
        while (temp != null) {
            length++;
            temp = temp.next;
        }
        return length;
    }
}

4.2 链表的快排

public Node sortList(Node head) {
    quickSort(head, null);
    return head;
}

public void quickSort(Node head, Node end) {
    if (head != null) {
        Node node = partion(head, end);
        quickSort(head, node);
        quickSort(node.next, end);
    }
}

public Node partion(Node head, Node end) {
    Node p1 = head, p2 = head.next;
    while (p2 != end) {
        if (p2.data < head.data) {
            p1 = p1.next;
            int temp = p1.data;
            p1.data = p2.data;
            p2.data = temp;
        }
        p2 = p2.next;
    }
    if (p1 != head) {
        int temp = p1.data;
        p1.data = head.data;
        head.data = temp;
    }
    return p1;
}

4.3 快排的最好最坏平均时间复杂度

平均时间复杂度 最好情况 最坏情况 空间复杂度
O(nlogn) O(nlogn) O(n2) O(1)

五、简历其他内容讨论

1、制作微信小程序的大致流程。
2、兼职辅导员的主要工作。

发布了90 篇原创文章 · 获赞 10 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/Fan0628/article/details/99583379