1.1
表1. 1 中若只包含编号为 1 和 4 的两个样例?试给出相应的版本空间.
表1.1的训练数据集对应的假设空间应该如下:
- 1 色泽=*,根蒂=*,敲声=*
- 2 色泽=青绿,根蒂=*,敲声=*
- 3 色泽=乌黑,根蒂=*,敲声=*
- 4 色泽=*,根蒂=蜷缩,敲声=*
- 5 色泽=*,根蒂=硬挺,敲声=*
- 6 色泽=*,根蒂=稍蜷,敲声=*
- 7 色泽=*,根蒂=*,敲声=浊响
- 8 色泽=*,根蒂=*,敲声=清脆
- 9 色泽=*,根蒂=*,敲声=沉闷
- 10 色泽=青绿,根蒂=蜷缩,敲声=*
- 11 色泽=青绿,根蒂=硬挺,敲声=*
- 12 色泽=青绿,根蒂=稍蜷,敲声=*
- 13 色泽=乌黑,根蒂=蜷缩,敲声=*
- 14 色泽=乌黑,根蒂=硬挺,敲声=*
- 15 色泽=乌黑,根蒂=稍蜷,敲声=*
- 16 色泽=青绿,根蒂=*,敲声=浊响
- 17 色泽=青绿,根蒂=*,敲声=清脆
- 18 色泽=青绿,根蒂=*,敲声=沉闷
- 19 色泽=乌黑,根蒂=*,敲声=浊响
- 20 色泽=乌黑,根蒂=*,敲声=清脆
- 21 色泽=乌黑,根蒂=*,敲声=沉闷
- 22 色泽=*,根蒂=蜷缩,敲声=浊响
- 23 色泽=*,根蒂=蜷缩,敲声=清脆
- 24 色泽=*,根蒂=蜷缩,敲声=沉闷
- 25 色泽=*,根蒂=硬挺,敲声=浊响
- 26 色泽=*,根蒂=硬挺,敲声=清脆
- 27 色泽=*,根蒂=硬挺,敲声=沉闷
- 28 色泽=*,根蒂=稍蜷,敲声=浊响
- 29 色泽=*,根蒂=稍蜷,敲声=清脆
- 30 色泽=*,根蒂=稍蜷,敲声=沉闷
- 31 色泽=青绿,根蒂=蜷缩,敲声=浊响
- 32 色泽=青绿,根蒂=蜷缩,敲声=清脆
- 33 色泽=青绿,根蒂=蜷缩,敲声=沉闷
- 34 色泽=青绿,根蒂=硬挺,敲声=浊响
- 35 色泽=青绿,根蒂=硬挺,敲声=清脆
- 36 色泽=青绿,根蒂=硬挺,敲声=沉闷
- 37 色泽=青绿,根蒂=稍蜷,敲声=浊响
- 38 色泽=青绿,根蒂=稍蜷,敲声=清脆
- 39 色泽=青绿,根蒂=稍蜷,敲声=沉闷
- 40 色泽=乌黑,根蒂=蜷缩,敲声=浊响
- 41 色泽=乌黑,根蒂=蜷缩,敲声=清脆
- 42 色泽=乌黑,根蒂=蜷缩,敲声=沉闷
- 43 色泽=乌黑,根蒂=硬挺,敲声=浊响
- 44 色泽=乌黑,根蒂=硬挺,敲声=清脆
- 45 色泽=乌黑,根蒂=硬挺,敲声=沉闷
- 46 色泽=乌黑,根蒂=稍蜷,敲声=浊响
- 47 色泽=乌黑,根蒂=稍蜷,敲声=清脆
- 48 色泽=乌黑,根蒂=稍蜷,敲声=沉闷
- 49 Ø
加入 1 号数据,(色泽=青绿、根蒂=蜷缩、敲声=浊响) 好瓜
,剩下
- 1 色泽=*,根蒂=*,敲声=*
- 2 色泽=青绿,根蒂=*,敲声=*
- 4 色泽=*,根蒂=蜷缩,敲声=*
- 7 色泽=*,根蒂=*,敲声=浊响
- 10 色泽=青绿,根蒂=蜷缩,敲声=*
- 16 色泽=青绿,根蒂=*,敲声=浊响
- 22 色泽=*,根蒂=蜷缩,敲声=浊响
- 31 色泽=青绿,根蒂=蜷缩,敲声=浊响
加入 4 号数据,(色泽=乌黑、根蒂=稍蜷、敲声=沉闷) 坏瓜
,剩下
- 2 色泽=青绿,根蒂=*,敲声=*
- 4 色泽=*,根蒂=蜷缩,敲声=*
- 7 色泽=*,根蒂=*,敲声=浊响
- 10 色泽=青绿,根蒂=蜷缩,敲声=*
- 16 色泽=青绿,根蒂=*,敲声=浊响
- 22 色泽=*,根蒂=蜷缩,敲声=浊响
- 31 色泽=青绿,根蒂=蜷缩,敲声=浊响
成功构建版本空间
1.2
与使用单个合取式来进行假设表示相比,使用"析合范式"将使得假设空间具有更强的表示能力。
例如
好瓜 <-> ((色泽=*(根蒂=蜷缩) ^ (敲声= *)) v ((色泽=乌黑) ^ (根蒂=*) ^ (敲声=沉闷))
会把(色泽=青绿)^(根蒂=蜷缩)^(敲声=清脆)
以及(色泽=乌黑) ^ (根蒂=硬挺) ^ (敲声=沉闷)
都分类为"好瓜"
若使用最多包含 k k k 个合取式的析合范式来表达。表1. 1 西瓜分类问题的假设空间, 试估算共有多少种可能的假设.
不会
- 48
从网上抄到一份代码(不过我觉得可以用动态规划试一试§(* ̄▽ ̄*)§)
import numpy as np
import itertools as it
def get_18_from_trible(trible): #把三维向量变为代表特征的18维向量
a = np.zeros([2,3,3])
a1 = trible[0]
a2 = trible[1]
a3 = trible[2]
if a1 == 3: #对于第一种属性为"*"的情况
a1 = [1,2]
else:
a1 = [a1]
if a2 == 4: #对于第二种属性为"*"的情况
a2 = [1,2,3]
else:
a2 = [a2]
if a3 == 4: #对于第三种属性为"*"的情况
a3 = [1,2,3]
else:
a3 = [a3]
#print (a1,a2,a3)
#print(a)
for m1 in a1:
for m2 in a2:
for m3 in a3:
a[m1-1][m2-1][m3-1] = 1
return a #得到了一个18维向量(0/1二值),代表18种特征情况
def turn_48_to_trible(num):
# num in [0,47],把一个小于48的数字对应到一个三维数组中
for i in range(3):
for j in range(4):
for k in range(4):
if i*16 + j*4 + k == num:
return [i+1,j+1,k+1]
def from_48_to_18(num): #把0-47的某个数唯一对应到某个18维向量
a = turn_48_to_trible(num)
b = get_18_from_trible(a)
return b
def main(k):
rset=[]
for i in it.combinations(range(48),k):
#开始对48取k的组合数进行穷举,i是一个k元数组
subset=[]
for j in range(k):
p = from_48_to_18(i[j])
subset.append(p)
subset = np.array(subset)
subset = subset.any(axis=0) # 这是去除冗余操作!!!
subset = np.reshape(subset,[18])
subset = subset.tolist() #从array变为list方便接下来的操作
count = 0
for i in range(18):
count += 2 ** i *subset[i]
#这是简单的一一映射,18维二值向量可以一一对应到1~2^18的某个数
subset = count
length = len(rset)
rset.append(subset)
if len(rset) % 100000 == 0 :
print(len(rset)) #为了证明程序确实在运行hhh,这个可以注释掉
if len(rset) > 5000000:
rset = list(set(rset)) #set是集合,是对rset数组进行去重!
#设置500W上限为了防止set操作时数组长度太长导致程序崩掉
rset = list(set(rset)) #最终set操作一下得到最终结果
#rset = list(set(tuple(t) for t in rset))
print( "%d : %d examples"%(k,len(rset)))
# main(k) 运行即得k个析取范式的结果。注:当k≥9时花费时间过长!目前没法解决!
这里笔者也给出自己写的题解,和部分网上答案不一致,不保证准确性。
更新:和这篇博客的答案一致
#include <bits/stdc++.h>
using namespace std;
bitset<2 << 18> bset;
vector<int> single; // 单个合取范式匹配的位置
int color = 2, root = 3, sound = 3;
int foo(int i, int j, int k, int val = 0) {
if (i == 0) {
for (int x = 1; x <= color; ++x) {
val |= foo(x, j, k, val);
}
return val;
}
if (j == 0) {
for (int x = 1; x <= root; ++x) {
val |= foo(i, x, k, val);
}
return val;
}
if (k == 0) {
for (int x = 1; x <= sound; ++x) {
val |= foo(i, j, x, val);
}
return val;
}
int no = (i - 1) * (root * sound) + (j - 1) * sound + k - 1;
return val | (1 << no);
}
void build_vec() {
for (int i = 0; i <= color; ++i) {
for (int j = 0; j <= root; ++j) {
for (int k = 0; k <= sound; ++k) {
single.push_back(foo(i, j, k));
}
}
}
}
// 组合型枚举板子
void comb(int k, int depth = 0, int start = 0, int val = 0) {
if (depth > 0) {
// for (size_t i = 1; i < depth; i++)
// cerr << "\t";
// cerr << "Choose: " << start - 1 << "\n";
}
if (depth >= k) {
// cerr << "Val: " << val << endl;
bset.set(val);
} else {
for (int i = start; i < single.size(); i++) {
comb(k, depth + 1, i + 1, val | single[i]); // 选择 i号假设
}
}
}
int main(int argc, char const *argv[]) {
// 首先直接枚举 k=1的情况
build_vec();
int k;
cin >> k;
for (int i = 1; i <= k; ++i) {
comb(i);
cout << "i=" << i << "\tans=" << bset.count() << endl;
}
/* code */
return 0;
}
以上代码在 k ≥ 9 k\geq 9 k≥9时计算较慢,我使用动态规划改进了一下:
这里使用了假设:
a
n
s
k
=
a
n
s
k
−
1
∨
a
n
s
k
=
1
ans_k = ans_{k-1} \vee ans_{k=1}
ansk=ansk−1∨ansk=1
也就是说要求最多使用k个,可以先只使用k-1个,然后将k-1个的结果再加上单个范式组合起来,复杂度不超过2^18 * 48
能在1s内计算完成。
#include <bits/stdc++.h>
using namespace std;
bitset<2 << 18> bset;
vector<int> single; // 单个合取范式匹配的位置
int color = 2, root = 3, sound = 3;
int foo(int i, int j, int k, int val = 0) {
if (i == 0) {
for (int x = 1; x <= color; ++x) {
val |= foo(x, j, k, val);
}
return val;
}
if (j == 0) {
for (int x = 1; x <= root; ++x) {
val |= foo(i, x, k, val);
}
return val;
}
if (k == 0) {
for (int x = 1; x <= sound; ++x) {
val |= foo(i, j, x, val);
}
return val;
}
int no = (i - 1) * (root * sound) + (j - 1) * sound + k - 1;
return val | (1 << no);
}
void build_vec() {
for (int i = 0; i <= color; ++i) {
for (int j = 0; j <= root; ++j) {
for (int k = 0; k <= sound; ++k) {
single.push_back(foo(i, j, k));
}
}
}
}
int main(int argc, char const *argv[]) {
// 首先直接枚举 k=1的情况
build_vec();
for (auto fansi : single) {
bset.set(fansi);
}
int k;
cin >> k;
for (int i = 1; i < k; ++i) {
cout << "i=" << i << "\tans=" << bset.count() << endl;
// 对每个现有范式组合结果 添加 新范式
auto bs = bset;
for (int i = 0; i < bs.size(); ++i) {
if (bs.test(i)) {
for (int fansi : single) {
bset.set(i | fansi); // 原有范式 | 新范式
}
}
}
}
cout << "i=" << k << "\tans=" << bset.count() << endl;
/* code */
return 0;
}
输出:
$ ./a.out
48
i=1 ans=48
i=2 ans=897
i=3 ans=8385
i=4 ans=41742
i=5 ans=115821
i=6 ans=201303
i=7 ans=248853
i=8 ans=260787
i=9 ans=262143
i=10 ans=262143
i=11 ans=262143
...后面全是262143了
1.3
若数据包含噪声,则假设空间中有可能不存在与所有训练样本都一致的假设。在此情形下,试设计一种归纳偏好用于假设选择.
- 假设噪声点很少:少数服从多数,如果统计相同标签下分类数,取占比多的
- 对于感知机算法:使用PosketAlgorithm改善
- 对于SVM算法:使用软间隔SVM
- 假设噪声点服从高斯分布:使用最小二乘法
- 最小二乘法对于离群值敏感,如果存在极端的噪声值,可能需要考虑采用鲁棒回归方法或者其他方法来处理。
1.4
前面忘了,中间忘了,总之成立
KaTeX parse error: Expected 'EOF', got '&' at position 58: …id X, f\right) &̲=& \sum_{h} \su…
1.5
试述机器学习能在互联网搜索的哪曲环节起什么作用.
- NLP,关键词检索
- 图像识别:以图搜图
- 爬虫后数据分析,pagerank网页排序算法
- 文字搜图
- 带歧义的搜索?