非标准解答,皆有参考,若有错误,请指正!
第一题
此题参考了博客: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(['青绿', '蜷缩', '浊响'])
第二题
此题参考了博客:https://blog.csdn.net/yuzeyuan12/article/details/83113461
下面描述不清楚的也可以参考着上述博客来回看,算是相互补充。
但我感觉还不太通俗,实质上我在一开始都没明白题目问什么,现在我要来解释一下题目到底让我们做什么。
题目给出好瓜,是由两个合取式的析取式定义出来的,第一个合取式中色泽有两种选择,敲声有三种选择,即2*3种,第二个合取式中根蒂有三种选择,组合起来即 2 ∗ 3 ∗ 3 2*3*3 2∗3∗3共计18种好瓜。那每一种好瓜都应该对应了一个三维向量,对应色泽、根蒂、敲声三种特征。这18种任意一种特征组合就能辨别好瓜,这是好瓜的版本空间。
分析了好瓜的特征空间,接下来描述整个特征空间,应该是 3 ∗ 4 ∗ 4 3*4*4 3∗4∗4的大小。色泽 = { 青绿 , 乌黑 , ∗ } =\{青绿,乌黑,*\} ={ 青绿,乌黑,∗},根蒂 = { 蜷缩 , 硬挺 , 稍蜷 , ∗ } =\{蜷缩,硬挺,稍蜷,*\} ={ 蜷缩,硬挺,稍蜷,∗},敲声 = { 浊响 , 清脆 , 沉闷 , ∗ } =\{浊响,清脆,沉闷,*\} ={ 浊响,清脆,沉闷,∗}。那么共计48种,这是全体瓜的版本空间。
那么题目所说的k个合取式要这么理解吧,比如k=2的时候,就相当于限定为两个合取式的析取,暂且将这两个合取式分别命作A、B,这两个合取式分别都取自全体特征空间的某一项,有几种组合嘞,粗暴的说,A有48种,B也有48种,所以是 48 ∗ 48 = 2304 48*48=2304 48∗48=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)
第三题
题目描述:若数据包含噪声,则假空间中有可能不存在与所有训练样本都一致的假设。在此情形下,试设计一种归纳偏好用于假设选择。
题目涉及归纳偏好的用处:在书中描述:“对于一个瓜(色泽=青绿;根蒂=蜷缩;敲声=沉闷),学得模型时而告诉我这是好瓜,时而告诉我这是坏瓜,这样的学习没有意义”。也就是结果出现了二义性,相当于一个