习题
习题1.1 表1.1中若只包含编号为1,4的两个样例,试给出相应的版本空间。
如下为西瓜的数据集:
编号 | 色泽 | 根蒂 | 敲声 | 好瓜 |
1 | 青绿 | 蜷缩 | 浊响 | 是 |
2 | 乌黑 | 稍蜷 | 沉闷 | 否 |
数据集中有三种属性,每种属性有2种可能取值,则一共有3 * 3 * 3 + 1 = 28种假设(考虑到泛化*,空集Ø的情况)。如下给出西瓜的假设空间:
去掉那些与正例不一致的假设,最终形成的版本空间如下:
即版本空间有下面这7种:
- (色泽=青绿;根蒂=*;敲声=*)
- (色泽=*;根蒂=蜷缩;敲声=*)
- (色泽=*;根蒂=*;敲声=浊响)
- (色泽=青绿;根蒂=蜷缩;敲声=*)
- (色泽=青绿;根蒂=*;敲声=浊响)
- (色泽=*;根蒂=蜷缩;敲声=浊响)
- (色泽=青绿;根蒂=蜷缩;敲声=浊响)
计算西瓜的假设空间和版本空间的程序如下:
package com.zfx.ml.watermelon.example.ch1.exercise1; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; /** * 《机器学习 - 周志华》第一章练习1.1中的西瓜假设空间程序和版本空间 * */ public class WatermelonExample { private List<Watermelon> examples = new ArrayList<>(); private Set<String> warnaSet = new LinkedHashSet<>(); private Set<String> rootSet = new LinkedHashSet<>(); private Set<String> knockingSet = new LinkedHashSet<>(); private List<Watermelon> positiveExamples = new ArrayList<>(); private List<Watermelon> hypothesisSpace = new ArrayList<>(); private List<Watermelon> versionSpace = new ArrayList<>(); public WatermelonExample(List<Watermelon> examples) { this.examples = examples; initPropertiesAndPositiveExample(); calculateHypothesisSpace(); calculateVersionSpace(); } /** 初始化属性和正例 */ private void initPropertiesAndPositiveExample() { for (Watermelon example : examples) { warnaSet.add(example.warna); rootSet.add(example.root); knockingSet.add(example.knocking); if (example.isGood()) { positiveExamples.add(example); } } warnaSet.add("*"); rootSet.add("*"); knockingSet.add("*"); } /** 计算西瓜的假设空间 */ private void calculateHypothesisSpace() { hypothesisSpace = new ArrayList<>(); for (String warna : warnaSet) { for (String root : rootSet) { for (String knocking : knockingSet) { boolean isGoodWatermelon = isGoodWatermelon(warna, root, knocking); hypothesisSpace.add(new Watermelon(warna, root, knocking, isGoodWatermelon)); } } } // 加上空集的情况 hypothesisSpace.add(Watermelon.EMPTY); } /** 计算西瓜的版本空间 */ private void calculateVersionSpace() { for (Watermelon h : hypothesisSpace) { // 所有属性是否都是泛化的 boolean isAllPropGeneralize = "*".equals(h.warna) && "*".equals(h.root) && "*".equals(h.knocking); if (h.isGood() && !isAllPropGeneralize) { // 去掉所有属性都是泛化的情况 versionSpace.add(h); } } } /** 是否为好瓜 */ private boolean isGoodWatermelon(String warna, String root, String knocking) { for (Watermelon positiveExample : positiveExamples) { int count = 0; if ("*".equals(warna) || positiveExample.warna.equals(warna)) { count ++; } if ("*".equals(root) || positiveExample.root.equals(root)) { count ++; } if ("*".equals(knocking) || positiveExample.knocking.equals(knocking)) { count ++; } if (count == 3) { return true; } } return false; } public List<Watermelon> getHypothesisSpace() { return hypothesisSpace; } public List<Watermelon> getVersionSpace() { return versionSpace; } public static class Watermelon { /** 表示Ø */ public static final Watermelon EMPTY = new Watermelon(null, null, null, null) { @Override public String toString() { return "Ø"; } }; final Boolean isGood; // 是否为好瓜 final String warna; // 色泽 final String root; // 根蒂 final String knocking; // 敲声 public Watermelon(String warna, String root, String knocking, Boolean isGood) { this.warna = warna; this.root = root; this.knocking = knocking; this.isGood = isGood; } /** 是否为好瓜 */ public boolean isGood() { return isGood != null && isGood; } @Override public String toString() { return "(色泽=" + warna + ";根蒂=" + root + ";敲声=" + knocking + ")"; } } public static void main(String[] args) { List<Watermelon> examples = new ArrayList<>(); examples.add(new Watermelon("青绿", "蜷缩", "浊响", true)); examples.add(new Watermelon("乌黑", "稍蜷", "沉闷", false)); WatermelonExample whs = new WatermelonExample(examples); List<Watermelon> ws = whs.getHypothesisSpace(); System.out.println("西瓜的假设空间如下:"); for (int i = 0; i < ws.size(); i++) { System.out.println((i + 1) + ":" + ws.get(i)); } List<Watermelon> vs = whs.getVersionSpace(); System.out.println(); System.out.println("西瓜的版本空间如下:"); for (int i = 0; i < vs.size(); i++) { System.out.println((i + 1) + ":" + vs.get(i)); } } }
习题1.2 与使用单个合取式来进行假设表示相比,使用“析合范式”将使得假设空间具有更强的表示能力。若使用最多包含k个合取式的析合范式来表达1.1的西瓜分类问题的假设空间,试估算有多少种可能的假设。
先解释下相关概念:
- 合取式( conJunction):用合取真值联结词“∧”将两个或两个以上的命题联结起来而形成的命题形式。合取联结词“并且”用符号“∧”来表示(“∧"读为合取),构成合取式的支命题,称做合取项。合取式一般表示为“p∧q”,只要其中一项为假,则整个命题为假。
- 析取式(disjunction):用析取真值联结词“∨”将两个或两个以上的命题联结起来而形成的命题形式。析取联结词“并且”用符号“∨”来表示(“∨"读为析取),构成析取式的支命题,称做析取项。析取式一般表示为“p∨q”,只要其中一项为真,则整个命题为真。
- 析合范式:即多个合取式的析取,例如:(p1∧q1)∨(p2∧q2)
表1.1中有4个样例,共有3个属性,则共有3 * 4 * 4 + 1 = 49种假设,若使用k个合取式的析合范式来表示1.1西瓜分类的假设空间,很显然k的取值范围为[1, 49],在不考虑空集的情况下,k的取值范围为[1, 48]。很显然,
- 具体假设(没有泛化的属性)的假设有:2 * 3 * 3 = 18(种)
- 1个属性泛化的假设有:1 * 3 * 3 + 2 * 1 * 3 + 2 * 3 * 1 = 21(种)
- 2个属性泛化的假设有:2 * 1 * 1 + 1 * 3 *1 + 1 * 1 * 3 = 8(种)
- 3个属性泛化的假设有: 1 * 1 * 1 = 1(种)
很显然有:
- 当 k = 1时,任选一种假设都可以作为没有冗余的假设,共有48种