概念學習-候選消除算法-Python實現

本文最後修改時間:20180330
##1、概念學習原型
已知
實例空間 X :使用屬性描述的實例(定義域)
概念空間 C :目標概念集合(值域)
假設空間 H :假設集合 (各種映射的集合)
訓練集合 D :目標概念的正例和反例 (已知的點)
x1,c(x1),x2,c(x2),...,xm,c(xm)\langle x_{1} , c(x_{1})\rangle,\langle x_{2} , c(x_{2})\rangle,...,\langle x_{m} , c(x_{m})\rangle
求解(找到一個一一映射的函數)
假設 h :滿足 h H\in\mathcal{H} 且 h(x) = c(x) , x D\in\mathcal{D}
個人理解,舉個簡單的栗子:二維座標中,已知兩個點的座標(0,0)、(1,1),求一個經過這兩點的線,比如有直線y=x,2次曲線y=x2y=x^{2},還有3次曲線y=x3y=x^{3},…,y=xny=x^{n}。x座標軸上的點組成的集合就是實例空間X,y座標軸上的點組成的集合就是概念空間C,這些曲線對應的函數集合就是假設空間H,已知的點座標就是訓練集合D
##2、變形空間
定義:一條假設 h 與訓練樣例集合 D\mathcal{D} 是一致的,當且僅當對 D\mathcal{D} 中每條樣例 x,c(x)\langle x, c(x)\rangle都有,即
Consistent(h,D)(x,c(x)D)h(x)=c(x))Consistent(h, \mathcal{D})\equiv(\forall\langle x, c(x)\rangle\in\mathcal{D})h(x)=c(x))
定義:假設空間 H\mathcal{H} 和訓練樣例集合 D\mathcal{D} 的變型空間,是 D\mathcal{D} 中與訓練樣例集合 H\mathcal{H} 一致的所有假設h構成的
子集合,標記爲 VSH,DVS_{\mathcal{H, D}} ,即
VSH,D{hHConsistent(h,D)}VS_{\mathcal{H, D}} \equiv \{h\in\mathcal{H} | Consistent(h, \mathcal{D})\}
##3、列表消除算法

  1. 變型空間 VS <-- 假設空間中所有假設列表
  2. 對每個訓練樣例 x,c(x)\langle x, c(x)\rangle ,從變型空間 VS 中刪除
    所有滿足 h(x)c(x)h(x) \not= c(x) 的假設 h
  3. 輸出變形空間 VS 中的假設列表

##4、候選消除算法
將G集合初始化爲H中極大一般假設
將S集合初始化爲H中極大特殊假設
對每個訓練例d,進行以下操作:
如果d是一正例
    • 從G中移去所有與d不一致的假設
     • 對S中每個與d不一致的假設s
       •從S中移去s
       • 把s的所有的極小一般化式h加入到S中,其中h滿足
         •h與d一致,而且G的某個成員比h更一般
     • 從S中移去所有這樣的假設:它比S中另一假設更一般
如果d是一個反例
    • 從S中移去所有d不一致的假設
     • 對G中每個與d不一致的假設g
       •從G中移去g
       •把g的所有的極小特殊化式h加入到G中,其中h滿足
         •h與d一致,而且S的某個成員比h更特殊
     •從G中移去所有這樣的假設:它比G中另一假設更特殊

# -*- coding: utf-8 -*-
import os
import pandas as pd

def loadData():
    '''數據
Sunny Hot High Week No
Sunny Hot High Strong No
Overcast Hot High Weak Yes
Rain Mild High Weak Yes
Rain Cool Normal Weak Yes
Overcast Cool Normal Strong Yes
Sunny Mild High Weak No
Sunny Cool Normal Weak Yes
Rain Mild Normal Weak Yes
Sunny Mild Normal Strong Yes
Overcast Mild High Strong Yes
Overcast Hot Normal Weak Yes
Rain Mild High Strong No
'''
    set = []
    data = pd.read_csv('data2.txt', sep=r' ', encoding="utf-8", engine='python', header=None)
    for i in xrange(len(data)):
        instance = []
        #print data.iloc[i]
        if 'Sunny' == data.iloc[i][0]:
            instance.append(1);
        elif 'Overcast' == data.iloc[i][0]:
            instance.append(2);
        else: #Rain
            instance.append(4);
                    
        if 'Hot' == data.iloc[i][1]:
            instance.append(1);
        elif 'Mild' == data.iloc[i][1]:
            instance.append(2);
        else: #Cool
            instance.append(4);
            
        if 'High' == data.iloc[i][2]:
            instance.append(1);
        else: #Normal
            instance.append(2);
        
        if 'Strong' == data.iloc[i][3]:
            instance.append(1);
        else: #Weak
            instance.append(2);
        
        if 'Yes' == data.iloc[i][4]:
            instance.append(1);
        else: #No
            instance.append(0);
        set.append(instance)
    return set

#判斷假設與實例是否一致,代碼和isMoreGeneralOrEqual一樣
#h : hypothesis 假設
#d : 訓練實例

def isConsistent(h, d):
    if d[4]: #d爲h的正例,h包含d時一致,否則不一致
        for i in xrange(4):
            if not (h[i] == (h[i] | d[i])): #不包含
                return False
        return True
    else: #d爲h的反例,h不包含d時一致,否則不一致
        for i in xrange(4):
            if not (h[i] == (h[i] | d[i])): #不包含
                return True
        return False
    
#h1 >= h2 h1是否比h2更一般
#h1 : hypothesis 假設1
#h2 : hypothesis 假設2
def isMoreGeneralOrEqual(h1, h2):
    for i in xrange(4):
        if not (h1[i] == (h1[i] | h2[i])): #不包含
            return False
    return True

#生成滿足d的極小一般化假設,只能生成1個
def genMinGeneralHypothesis(s, d):
    h = []
    for i in xrange(4):
        if s[i] == d[i]:
            h.append(s[i])
        else:
            h.append(s[i] | d[i])
    return h

#生成滿足d的極小特殊化假設,最多可以生成n個,n爲維度
def genMinSpecialHypothesis(g, d):
    setH = []
    for i in xrange(4):
        h = list(g)
        if not (g[i] == (g[i] | d[i])): #g[i]不包含d[i]
            continue
        else:
            #去掉d[i]都的特徵值,並添加到候選假設集
            h[i] = (g[i] & ~d[i]) 
            setH.append(h)
    return setH

def printResult(set):
    print '[',
    for i in xrange(len(set)):
        print '[',
        if 7 == set[i][0]:
            print '?',
        elif 0 == set[i][0]:
            print '0',
        else:
            if 4 & set[i][0]:
                print 'Rain',
            if 2 & set[i][0]:
                print 'Overcast',
            if 1 & set[i][0]:
                print 'Sunny',
        print ',',
            
        if 7 == set[i][1]:
            print '?',
        elif 0 == set[i][1]:
            print '0',
        else:
            if 4 & set[i][1]:
                print 'Cool',
            if 2 & set[i][1]:
                print 'Mild',
            if 1 & set[i][1]:
                print 'Hot',
        print ',',

        if 3 == set[i][2]:
            print '?',
        elif 2 == set[i][2]:
            print 'Normal',
        elif 1 == set[i][2]:
            print 'High',
        else:
            print '0',
        print ',',
        
        if 3 == set[i][3]:
            print '?',
        elif 2 == set[i][3]:
            print 'Weak',
        elif 1 == set[i][3]:
            print 'Strong',
        else:
            print '0',
        print '], ',
    print ']'

def main():
    setS = [[0, 0, 0, 0]] #極大特殊假設
    setG = [[7, 7, 3, 3]] #極大一般假設
    data = loadData()
    for i in xrange(len(data)):
        if data[i][4]: #正例
            #從G中移去所有與d不一致的假設
            j = 0
            while j < len(setG):
                if not isConsistent(setG[j], data[i]):
                    setG.pop(j)
                    j = j - 1
                j = j + 1
            #對S中每個與d不一致的假設s , 從S中移去s
            #並把s的所有的極小一般化式h加入到S中,其中h滿足 : h與d一致,而且G的某個成員比h更一般
            j = 0
            while j < len(setS):
                if not isConsistent(setS[j], data[i]):
                    #極小一般化式h  感覺只能添加一個h
                    h = genMinGeneralHypothesis(setS[j], data[i])
                    #從S中移去s
                    setS.pop(j)
                    j = j - 1
                    for k in xrange(len(setG)):
                        if isMoreGeneralOrEqual(setG[k], h):
                            setS.append(h)
                j = j + 1            

            #從S中移去所有這樣的假設:它比S中另一假設更一般
            j = 0
            while j < len(setS):
                k = j + 1
                while k < len(setS):
                    if isMoreGeneralOrEqual(setS[j], setS[k]):
                        setS.pop(j)
                        j = j - 1
                        break
                    elif isMoreGeneralOrEqual(setS[k], setS[j]):
                        setS.pop(k)
                        continue
                    k = k + 1
                j = j + 1

        else: #反例
            #從S中移去所有d不一致的假設
            j = 0
            while j < len(setS):
                if not isConsistent(setS[j], data[i]):
                    setS.remove(j)
                    j = j - 1
                j = j + 1
            
            #對G中每個與d不一致的假設g,從G中移去g            
            #並把g的所有的極小特殊化式h加入到G中,其中h滿足:h與d一致,而且S的某個成員比h更特殊
            j = 0
            while j < len(setG):
                if not isConsistent(setG[j], data[i]):
                    #極小特殊化式h
                    setH = genMinSpecialHypothesis(setG[j], data[i])
                    #從G中移去g
                    setG.pop(j)
                    j = j - 1
                    for m in xrange(len(setH)):                        
                        for k in xrange(len(setS)):
                            if isMoreGeneralOrEqual(setH[m], setS[k]):
                                setG.append(setH[m])
                j = j + 1
            
            #從G中移去所有這樣的假設:它比G中另一假設更特殊
            j = 0
            while j < len(setG):
                k = j + 1
                while k < len(setG):
                    if isMoreGeneralOrEqual(setG[j], setG[k]):
                        setG.pop(k)
                        continue
                    elif isMoreGeneralOrEqual(setG[k], setG[j]):
                        setG.pop(j)
                        j = j - 1
                        break
                    k = k + 1
                j = j + 1
        if i < len(data) - 1:
            print 'D' + str(i+1)
            print setS
            print setG
            printResult(setS)
            printResult(setG)
        print ''
    return


if __name__ == "__main__":
    main()

輸出結果:

D1
[[0, 0, 0, 0]]
[[6, 7, 3, 3], [7, 6, 3, 3], [7, 7, 2, 3], [7, 7, 3, 1]]
[ [ 0 , 0 , 0 , 0 ],  ]
[ [ Rain Overcast , ? , ? , ? ],  [ ? , Cool Mild , ? , ? ],  [ ? , ? , Normal , ? ],  [ ? , ? , ? , Strong ],  ]

D2
[[0, 0, 0, 0]]
[[6, 7, 3, 3], [7, 6, 3, 3], [7, 7, 2, 3], [7, 7, 3, 0]]
[ [ 0 , 0 , 0 , 0 ],  ]
[ [ Rain Overcast , ? , ? , ? ],  [ ? , Cool Mild , ? , ? ],  [ ? , ? , Normal , ? ],  [ ? , ? , ? , 0 ],  ]

D3
[[2, 1, 1, 2]]
[[6, 7, 3, 3]]
[ [ Overcast , Hot , High , Weak ],  ]
[ [ Rain Overcast , ? , ? , ? ],  ]

D4
[[6, 3, 1, 2]]
[[6, 7, 3, 3]]
[ [ Rain Overcast , Mild Hot , High , Weak ],  ]
[ [ Rain Overcast , ? , ? , ? ],  ]

D5
[[6, 7, 3, 2]]
[[6, 7, 3, 3]]
[ [ Rain Overcast , ? , ? , Weak ],  ]
[ [ Rain Overcast , ? , ? , ? ],  ]

D6
[[6, 7, 3, 3]]
[[6, 7, 3, 3]]
[ [ Rain Overcast , ? , ? , ? ],  ]
[ [ Rain Overcast , ? , ? , ? ],  ]

D7
[[6, 7, 3, 3]]
[[6, 7, 3, 3]]
[ [ Rain Overcast , ? , ? , ? ],  ]
[ [ Rain Overcast , ? , ? , ? ],  ]

D8
[]
[]
[ ]
[ ]

D9
[]
[]
[ ]
[ ]

D10
[]
[]
[ ]
[ ]

D11
[]
[]
[ ]
[ ]

D12
[]
[]
[ ]
[ ]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章