西瓜书第一章课后习题

非标准解答,皆有参考,若有错误,请指正!

第一题

此题参考了博客:https://blog.csdn.net/MaxQuYY/article/details/120287245
假设空间: 所有假设组成的空间

版本空间:与训练集一致的假设集合

从假设空间到版本空间算法大致如下:

1.删除与正例不一致的假设且删除与反例一致的假设

2.删除与正例不一致的假设

3.删除与反例一致的假设
模仿西瓜书的图1.1写的一个从特殊到一般的这么个空间,再取消掉包含了反例的情况(这里就是全部为通配符的情况),保留正例的情况(即正例中的那些元素值,你得包含一个以上)
整个从特殊到一般的结构呢,就是下一层比上一层的每一项中多一个通配符

import copy


def get_next_res(input: list):
    # print(input)
    wil_card_position = []
    next_list = []
    for (index, item) in enumerate(input):
        if item == '*':
            wil_card_position.append(index)
    for (index, item) in enumerate(input):
        if item != '*':
            next_item = copy.copy(input)
            next_item[index] = '*'
            next_list.append(copy.copy(next_item))
    return next_list


def get_next_layer(layer: list):
    next_layer = []
    for item in layer:
        for next_res in get_next_res(item):
            if next_res not in next_layer:
                next_layer.append(next_res)
    return next_layer


def main(input: list):
    input_wil_card_position = []
    for (index, item) in enumerate(input):
        if item == '*':
            input_wil_card_position.append(index)
    layer = [input]
    print(layer)
    for i in range(len(input_wil_card_position), len(input)):
        layer = get_next_layer(layer)
        if layer != [['*', '*', '*']]:
            print(layer)


main(['青绿', '蜷缩', '浊响'])

1.1运行结果图

第二题

此题参考了博客:https://blog.csdn.net/yuzeyuan12/article/details/83113461
下面描述不清楚的也可以参考着上述博客来回看,算是相互补充。

但我感觉还不太通俗,实质上我在一开始都没明白题目问什么,现在我要来解释一下题目到底让我们做什么。
题目给出好瓜,是由两个合取式的析取式定义出来的,第一个合取式中色泽有两种选择,敲声有三种选择,即2*3种,第二个合取式中根蒂有三种选择,组合起来即 2 ∗ 3 ∗ 3 2*3*3 233共计18种好瓜。那每一种好瓜都应该对应了一个三维向量,对应色泽、根蒂、敲声三种特征。这18种任意一种特征组合就能辨别好瓜,这是好瓜的版本空间

分析了好瓜的特征空间,接下来描述整个特征空间,应该是 3 ∗ 4 ∗ 4 3*4*4 344的大小。色泽 = { 青绿 , 乌黑 , ∗ } =\{青绿,乌黑,*\} ={ 青绿,乌黑,},根蒂 = { 蜷缩 , 硬挺 , 稍蜷 , ∗ } =\{蜷缩,硬挺,稍蜷,*\} ={ 蜷缩,硬挺,稍蜷,},敲声 = { 浊响 , 清脆 , 沉闷 , ∗ } =\{浊响,清脆,沉闷,*\} ={ 浊响,清脆,沉闷,}。那么共计48种,这是全体瓜的版本空间

那么题目所说的k个合取式要这么理解吧,比如k=2的时候,就相当于限定为两个合取式的析取,暂且将这两个合取式分别命作A、B,这两个合取式分别都取自全体特征空间的某一项,有几种组合嘞,粗暴的说,A有48种,B也有48种,所以是 48 ∗ 48 = 2304 48*48=2304 4848=2304种,但是它有重复的呀,比方说(A,B)=(1,2)和(A,B)=(2,1),对于析取 ∨ \vee 来说,左右换个顺序是没差的,那么真正意义上应该是for i in range(48) for j in range(i,48)这样的一个循环,那么就是 48 + 47 + 46 + . . . + 1 48+47+46+...+1 48+47+46+...+1这样,共计 48 ∗ ( 48 + 1 ) / 2 48*(48+1)/2 48(48+1)/2种,对于每一种 (要把好瓜的特征空间变成18位二进制的十八维向量,某位为0代表没那个特征,某位为1代表有那个特征,共计 2 18 2^{18} 218种表示),将其映射到一维向量,生成对应的假设,两个假设的组合是当前取了k个合取式假设,而我们要求的便是当前取了k个合取式共有几种假设。

求解:给定一个K,那么就是K个合取式,每个合取式 X i X_i Xi种取值, ( X 0 , X 1 , . . . , X i ) (X_0,X_1,...,X_i) (X0,X1,...,Xi),对于每一种 X X X取值组合,生成K个合取式,每个合取式对应的特征空间的一种,最后将这K个合取式进行析取,得到一种假设,遍历完这些 X X X取值组合的 ( X 0 , X 1 , . . . , X i ) (X_0,X_1,...,X_i) (X0,X1,...,Xi)之后,对假设空间进行去重,去重后的数量便是假设空间的数量了。

下面给出代码:

import numpy as np
import itertools as it

dimension = np.array([2, 3, 3])  # 定义维度

def dimensional_from_three_to_eighteen(vector) -> type(np.array):
    """
    根据向量Vector里的值给他变换成(2,3,3)的矩阵再拉成一维向量
    :param vector:向量=>(2,3,3)=>18
    :return:res_vector返回的一维向量
    """

    res_vector = np.zeros(dimension)  # 初始化
    for i in range(
            len(vector)):  # 对于向量的每一项,进行通配符*向全数值列表的替换,(3,4,4)分别代表1,2,3位置上的通配符
        if vector[i] != dimension[i] + 1:
            vector[i] = [vector[i]]  # 不替换
        else:
            vector[i] = [num for num in range(1, dimension[i] + 1)]  # 替换通配符
    # 向量中的每一项对应至三维向量的位置上置1
    for i in vector[0]:
        for j in vector[1]:
            for k in vector[2]:
                res_vector[i - 1][j - 1][k - 1] = 1
    return res_vector


def turn_num_to_three_dimension(num: int) -> list:
    """
    将数值0~48转化为对应的三维向量
    :param num: 按本题取值0~48
    :return:
    """
    composition = dimension + 1
    for i in range(composition[0]):
        for j in range(composition[1]):
            for k in range(composition[2]):
                if i * composition[1] * composition[2] + j * composition[
                    2] + k == num:
                    return [i + 1, j + 1, k + 1]


def convert_num_to_eighteen_dimension(num: int) -> type(np.array):
    """
    将对应数值转为一维向量
    :param num:按本题取值0~48
    :return:
    """
    return dimensional_from_three_to_eighteen(turn_num_to_three_dimension(
        num))


def main(k: int) -> int:
    res = []  # 用于装最后的结果列表
    index = 0  # 用于循环计数
    for i in it.combinations(range(48), k):  # 对48取k个值进行穷举
        index += 1
        res_set = []
        for j in range(k):  # 现在要生成K个合取式
            res_set.append(convert_num_to_eighteen_dimension(i[
                                                                 j]))  # 
            # res_set将一维向量装入,每个一维向量相当于一个合取式
        res_set = np.reshape(np.array(res_set).any(axis=0), [18]).tolist(

        )  # 将转出来几项向量(相当于几项合取式)进行or操作,即模拟析取,再转成列表以便后续操作
        count = 0
        for i in range(len(res_set)):  # 将二进制化成十进制数,即把列表变成一个数
            count += 2 ** i * res_set[i]  # 将二进制每一位化成十进制
        res.append(count)  # 将二进制表示的十进制数加入列表
        if index > 2000:  # 每循环两千次进行一次去重
            index = 0
            res = list(set(res))
	return len(res)

main(3)

第三题

题目描述:若数据包含噪声,则假空间中有可能不存在与所有训练样本都一致的假设。在此情形下,试设计一种归纳偏好用于假设选择。

题目涉及归纳偏好的用处:在书中描述:“对于一个瓜(色泽=青绿;根蒂=蜷缩;敲声=沉闷),学得模型时而告诉我这是好瓜,时而告诉我这是坏瓜,这样的学习没有意义”。也就是结果出现了二义性,相当于一个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值