《机器学习》西瓜书习题 第 3 章

习题

3.1

  试析在什么情况下式 \((3.2)\) 中不必考虑偏置项 \(b\) .
  书中有提到, 可以把 \(x\)\(b\) 吸收入向量形式 \(\hat{w} = (w;b)\) .此时就不用单独考虑 \(b\) 了.

3.2

  试证明, 对于参数 \(w\), 对率回归的目标函数 \((3.18)\) 是非凸的, 但其对数似然函数 \((3.27)\) 是凸的.
\[y = \frac{1}{1 + e^{-(\boldsymbol w^\mathrm T\boldsymbol x + b)}}\tag{3.18}\]
\[\ell(\boldsymbol\beta) = \sum^m_{i = 1}(-y_i\boldsymbol \beta^\mathrm T\boldsymbol{\hat{x}}_i)\tag{3.18}\]
(等我搞懂了再补充.)
## 3.3
  编程实现対率回归, 并给出西瓜数据集 \(3.0\alpha\) 上的结果.
## 3.5
  选择两个 \(UCI\) 数据集, 比较 \(10\) 折交叉验证法和留一法所估计出的错误率.
## 3.6
  线性判别分析仅在线性可分数据上能获得理想结果, 试设计一个改进方法, 使其能较好地用于飞线性可分数据.
  像 \(6.3\) 节介绍的那样, 使用核函数, 就可以运用于非线性可分数据.

3.7

  令码长为 \(9\), 类别数为 \(4\) , 试给出海明距离意义下理论最优的 \(ECOC\) 二元码并证明之.
  首先要给出理论最优, 我们先要确定 '最优' 的指导标准.

  对同等长度的编码, 理论上来说, 任意两个类别之间的编码距离越远, 则纠错能力越强.

  我们要将 '任意两个类别的编码距离' 用数学表达, 这样才能进行求解. 那么怎么用数学表达这个 '距离' 呢? 这里考虑到 '总体距离最大' , 所以我们浅显的使用每两个类别之间的海明距离的积来作为衡量标准. 我们定义一个变量 \(L\) 用来表达这个积, 也就是有
\[L = \prod_{1\leqslant i< j\leqslant 4}dis(r_i, r_j)\]
\(dis(r_i, r_j)\) 表示第 \(i\) 个编码和第 \(j\) 个编码之间的海明距离, 同时 \(L\) 越大代表这种编码方式越好.
  于是我写了段程序来搜索 \(L\) 的最大值 (直接爆搜) .

#include<iostream>
#include<cmath>
using namespace std;


const int MAXCOL = 9;  // 码长为 9 
const int MAXROW = 4;  // 类别数为 4 

bool code[MAXROW][MAXCOL];  // 记录最大值时编码排列
bool temp_code[MAXROW][MAXCOL];  // 表示当前编码排列

int mmax = 0;  // 记录最大值


int dif_val(bool a[MAXCOL], bool b[MAXCOL]){  // 求两个编码之间的海明距离
    int cnt = 0;
    for(int i = 0 ; i < MAXCOL ; ++i){
        if(a[i] != b[i])    ++cnt;
    }
    return cnt;
}

int cost(bool code[MAXROW][MAXCOL]){  // 求当前编码排列的 L
    int res = 1;
    for(int i = 0 ; i < MAXROW ; ++i){
        for(int j = i + 1 ; j < MAXROW ; ++j){
            res *= dif_val(code[i], code[j]);
        }
    }
    return res;
}

void dfs(int row = 2, int col = 0){  // 深度优先搜索, 枚举每个位置的编码 (0 和 1)
    if(row == MAXROW)    return;  // 边界条件
    temp_code[row][col] = 1;  // 先枚举 1
    int temp = cost(temp_code);
    if(mmax < temp){  // 发现更好的编码排列, 进行更新
        mmax = temp;
        for(int i = 0 ; i < MAXROW ; ++i)
            for(int j = 0 ; j < MAXCOL ; ++j)
                code[i][j] = temp_code[i][j];
    }
    if(col == MAXCOL - 1)    dfs(row + 1, 0);  // 下一层
    else    dfs(row, col + 1);
    temp_code[row][col] = 0;  // 返回再枚举 0
    temp = cost(temp_code);
    if(mmax < temp){  // 同上
        mmax = temp;
        for(int i = 0 ; i < MAXROW ; ++i)
            for(int j = 0 ; j < MAXCOL ; ++j)
                code[i][j] = temp_code[i][j];
    }
    if(col == MAXCOL - 1)    dfs(row + 1, 0);  // 同上
    else    dfs(row, col + 1);
    return ;
}

int main(){
    for(int i = 0 ; i < MAXCOL ; ++i){
        temp_code[0][i] = 1;  // 不失一般性, 令第一个类别的编码全部为 1 
    }
    for(int i = 1 ; i <= MAXCOL ; ++i){  // 不失一般性, 枚举第二个类别 1 的数量 (1 ~ 9)
        temp_code[1][i - 1] = 1;
        dfs();
    }
    for(int i = 0 ; i < MAXROW ; ++i){  // 打印最终结果
        for(int j = 0 ; j < MAXCOL ; ++j){
            cout << code[i][j] << ' ';
        }
        cout << endl;
    }
    cout << mmax;
    return 0;
}  // 我的码风是不是很好看

结果:

1 2 3 4 5 6 7 8 9
1 1 1 1 1 1 1 1 1 1
2 1 1 1 0 0 0 0 0 0
3 0 0 0 1 1 1 0 0 0
4 0 0 0 0 0 0 1 1 1

46656

当然我们要把 \(0\) 换成 \(-1\).
  所以, 我们求出了海明距离下理论最优的, 码长为 \(9\), 类别数为 \(4\)\(EOOC\) 二元码. 至于证明, 在我们定义的衡量标准下, 其正确性是显然的.

3.8*

  \(EOOC\) 编码能起到理想纠错作用的重要条件是: 在每一位编码上出错的概率相当且独立. 试析多分类任务经 \(EOOC\) 编码后产生的二类分类器满足该条件的可能性及由此产生的影响.
(同样的, 我搞懂了再补)

3.9

  使用 \(OvR\)\(MvM\) 将多分类任务分解为二分类任务求解时, 试述为何无需专门针对类别不平衡性进行处理.
  原文就已经提到

  对 \(OvR\)\(MvM\) 来说, 由于对每个类进行了相同的处理, 其拆解出的二分类任务中类别不平衡的影响会相互抵消, 因此通常不需要专门处理.

3.10*

  试推导出多分类代价敏感学习 (仅考虑基于类别的误分类代价) 使用 "再缩放" 能获得理论最优解的条件.
  原文中提到

  再缩放的思想虽简单, 但实际操作却并不平凡, 主要因为 "训练集是真实样本总体的无偏采样" 这个假设往往并不成立.

  因此假设成立应该也算是获得理论最优解的一个条件.

\(PS\): 题目好像越来越难了...

猜你喜欢

转载自www.cnblogs.com/cloud--/p/12150580.html