主頁 >  其他 > ID3演算法

ID3演算法

2020-09-24 08:56:31 其他

       ID3演算法最核心的思想是采用資訊增益來選擇特征,決策樹類的演算法最大的不同就是特征的選擇標準不同,C4.5采用資訊增益比,用于減少ID3演算法的局限(在訓練集中,某個屬性所取的不同值的個數越多,那么越有可能拿它來作為分裂屬性,而這樣做有時候是沒有意義的),CART演算法采用gini系數,不僅可以用來分類,也可以解決回歸問題,

        我這里的資料集采用mnist(二進制檔案),使用ID3來對圖片集進行分類,將每一個像素作為一個特征,為了提高預測的精確率,需要對圖片進行二值化處理,

        資訊增益計算公式:

        

        以下是ID3的源代碼,

# encoding=utf-8

import cv2
import time
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score



# 二值化
def binaryzation(img):
    cv_img = img.astype(np.uint8) # astype用于改變資料的型別   uint8是無符號八位(bit)整型,表示范圍是[0, 255]的整數
    # 原圖片,閾值,最大值,劃分時采用的演算法  大于50的點設定為0,其他的為最大值1
    cv2.threshold(cv_img, 50, 1, cv2.THRESH_BINARY_INV, cv_img) 
    return cv_img

def binaryzation_features(trainset):
    features = []
    for img in trainset:
        img = np.reshape(img,(28,28)) # 28行*28列,每一個元素代表一個像素值,元素的值是8位無符號整型
        cv_img = img.astype(np.uint8)
        img_b = binaryzation(cv_img)  # 此為上面自定義的函式
        # hog_feature = np.transpose(hog_feature)
        features.append(img_b)
    features = np.array(features) # 將list轉化為array
    features = np.reshape(features,(-1,feature_len)) # 我不知道可以分成多少行,但是我的需要是分成feature_len列(feature_len = 784) 
    return features


import os
import struct
import numpy as np

def load_mnist(path, kind='train'):
    labels_path = os.path.join(path, '%s-labels.idx1-ubyte' % kind)
    images_path = os.path.join(path, '%s-images.idx3-ubyte' % kind)
    with open(labels_path, 'rb') as lbpath:
        magic, n = struct.unpack('>II', lbpath.read(8)) # 一個I代表4個位元組,所以一共有8位元組的頭部,分別存入變數magic和n中
        labels = np.fromfile(lbpath, dtype=np.uint8) # 一個位元組一讀,并轉化為8位無符號整型
    with open(images_path, 'rb') as imgpath:
        magic, num, rows, cols = struct.unpack('>IIII', imgpath.read(16))
        images = binaryzation_features(np.fromfile(imgpath, dtype=np.uint8).reshape(len(labels), 784))
        # images = np.fromfile(imgpath, dtype=np.uint8).reshape(len(labels), 784) # 除去16個位元組的頭部之后,剩下的資料轉變為8位無符號整型
    return images, labels
    # 訓練集一共有9912422位元組,訓練集一共有60000個樣本,通過樣本數無法推得有那么多的位元組,應該是經過壓縮了的



# 決策樹的定義
class Tree(object):
    def __init__(self,node_type,Class = None, feature = None):
        self.node_type = node_type  # 節點型別(internal或leaf)
        self.dict = {}              # dict的鍵表示特征Ag的可能值ai,值表示根據ai得到的子樹,{特征值:子樹},采用字典的形式來描述樹型結構
        self.Class = Class          # 葉節點表示的類標記,若是內部節點則為none
        self.feature = feature      # 表示當前的樹即將由第feature個特征劃分(即第feature特征是使得當前樹中資訊增益最大的特征)

    def add_tree(self,key,tree):    # key代表的特征值,不同的key用于區分不同的子樹
        self.dict[key] = tree       # 一個key就是一條樹的分支

    def predict(self,features):     # features為當前待預測的一個樣本
        # 當樣本中采樣不全,結果在測驗集中出現了一個在樣本中從未出現過特征值,則搜索會在內部節點就直接終止,self.class便是None
        if self.node_type == 'leaf' or (features[self.feature] not in self.dict): 
            return self.Class       #  predict最侄訓傳的是樣本對應的類標記,
        tree = self.dict.get(features[self.feature]) # 找出第feature個特征所對應的特征值
        return tree.predict(features)  # 遞回搜索


# 計算資料集x的經驗熵H(x)——每一個類的樣本數量在所有類樣本資料中所占的比重
def calc_ent(x):  # 類列
    # 樣本中有那些類(樣本中的類可能不全),x的型別是array,先將其轉變為list,再變為set
    x_value_list = set([x[i] for i in range(x.shape[0])]) # 形成不重復的類集合
    ent = 0.0
    for x_value in x_value_list:
        p = float(x[x == x_value].shape[0]) / x.shape[0]  # 當前類的數量 / 總的類的數量
        logp = np.log2(p)
        ent -= p * logp # 計算熵,熵越大,隨機變數的不確定性就越大
    return ent


# 計算條件熵H(y/x)
def calc_condition_ent(x, y): # 特征列,類列
    x_value_list = set([x[i] for i in range(x.shape[0])]) # 某一特征中的所有不重復的特征值
    ent = 0.0
    for x_value in x_value_list:
        # 從x這一array陣列中依次遍歷,挑出其中與值x_value相同的,由于train_test_split的影響,其結果會直接對應y中的對應類
        sub_y = y[x == x_value] 
        temp_ent = calc_ent(sub_y) # sub_y是擁有相同特征值的不同的類的串列
        ent += (float(sub_y.shape[0]) / y.shape[0]) * temp_ent
    return ent


# 計算資訊增益
def calc_ent_grap(x,y):  # 特征列,類列
    base_ent = calc_ent(y) # 計算資料集x的經驗熵H(x)
    condition_ent = calc_condition_ent(x, y) # 計算條件熵H(y/x)
    ent_grap = base_ent - condition_ent
    return ent_grap


# ID3演算法
def recurse_train(train_set, train_label, features): # train_features, train_labels. 訓練集以及其對應的類串列  features為特征串列 
    LEAF = 'leaf'
    INTERNAL = 'internal'

    # 步驟1——如果訓練集train_set中的所有實體都屬于同一類Ck
    label_set = set(train_label)  # set可以理解為資料不重復的串列,且元素為不可變物件
    if len(label_set) == 1:
        return Tree(LEAF,Class = label_set.pop())

    # 步驟2——處理特征集為空時的情況
        # filter() 函式用于過濾序列,過濾掉不符合條件的元素,回傳由符合條件元素組成的迭代器物件,
        # lambda x:x==i,train_label,x指向train_label,依次搜索train_label中的每一個值,如果與i相等,則將其放入list中
        # 計算每一個類出現的個數,并用元組存放結果[(類標號,類的數量), ...]
    class_len = [(i,len(list(  filter(lambda x:x==i,train_label)  )))   for i in range(class_num)] 
    (max_class, max_len) = max(class_len, key = lambda x:x[1]) # 回傳串列中元組中的類數量最多的那個元組   x[1]類所對應的數量
        # 類, 類的數量 
    if len(features) == 0:  # features為特征集合
        return Tree(LEAF,Class = max_class)

    # 步驟3——計算資訊增益,并選擇資訊增益最大的特征
    max_feature = 0  # 能產生最大資訊增益的特征
    max_gda = 0      # 資訊增益的最大值
    D = train_label  # train_labels,訓練集對應的類串列
    for feature in features: # 從784個特征中依次選取特征計算器資訊增益
        A = np.array(train_set[:,feature].flat) # 選擇訓練集中的第feature列的所有特征值,.flat是將陣列轉換為1-D的迭代器
        gda=calc_ent_grap(A,D) # 計算資訊增益
        if gda > max_gda:
            max_gda,max_feature = gda,feature
'''
如果要寫C4.5演算法,那就可以直接在ID3演算法的基礎上,將用于特征選擇的資訊增益改為資訊增益比,即添加以下代碼:
ent = calc_ent(A)
if ent != 0:
gad /= ent
不過有意思的是,我曾將ID3改為C4.5來對MNIST進行學習分類,但是會報記憶體溢位錯誤,一直不明白這是怎么回事,因為我只是在ID3的基礎上多呼叫了一個calc_ent(A)函式,而且函式運行完畢也會將記憶體釋放的,怎么就會導致記憶體溢位呢?
'''
# 步驟4——資訊增益小于閾值,這里采用先剪枝演算法,防止過擬合 if max_gda < epsilon: return Tree(LEAF,Class = max_class) # 步驟5——構建非空子集 sub_features = list(filter(lambda x:x!=max_feature,features)) # 將已經使用過的特征從特征集中洗掉 tree = Tree(INTERNAL,feature=max_feature) # 當前樹節點是內部節點,將由feature特征繼續劃分樣本集 max_feature_col = np.array(train_set[:,max_feature].flat) # .flat是將陣列轉換為1-D的迭代器 # 保存資訊增益最大的特征可能的取值 (shape[0]表示計算行數) # y.shape 回傳的一個元組,代表 y 資料集的資訊如(行,列) y.shape[0], 意思是:回傳 y 中行的總數, # 這個值在 y 是單特征的情況下 和 len(y) 是等價的,即資料集中資料點的總數, # 依據特征值的不同將樣本分到不同的子樹 feature_value_list = set([max_feature_col[i] for i in range(max_feature_col.shape[0])]) for feature_value in feature_value_list: index = [] for i in range(len(train_label)): if train_set[i][max_feature] == feature_value: index.append(i) sub_train_set = train_set[index] # 將特征值同是feature_value的樣本放到一起,形成一個新的子樹樣本 sub_train_label = train_label[index] # 將樣本對應的類也封裝到一起,一起傳入子樹中 sub_tree = recurse_train(sub_train_set,sub_train_label,sub_features) # 遞回函式 tree.add_tree(feature_value,sub_tree) return tree def train(train_set,train_label,features): return recurse_train(train_set,train_label,features) def predict(test_set,tree): result = [] for features in test_set: tmp_predict = tree.predict(features) result.append(tmp_predict) # result存盤測驗集中的樣本對應的測驗得到的類 return np.array(result) # 將list陣列轉變為array陣列 class_num = 10 # MINST資料集有10種labels,分別是“0,1,2,3,4,5,6,7,8,9” feature_len = 784 # MINST資料集每個image有28*28=784個特征(pixels) epsilon = 0.01 if __name__ == '__main__':
print("ID3")
print("Start read data...") t1 = time.time() # basedir = os.path.dirname(__file__) train_features,train_labels = load_mnist("data" , kind='train') test_features,test_labels = load_mnist("data", kind='t10k') t2 = time.time() print("讀取資料用時:" + str((t2-t1))) print('Start training...') tree = train(train_features, train_labels, list(range(feature_len))) # 0-783的一個陣列,特征集 t3 = time.time() print("訓練資料用時:" + str((t3-t2))) print('Start predicting...') test_predict = predict(test_features,tree) # test_features測驗集,tree為訓練好的模型,函式回傳的型別為np.array t4 = time.time() print("預測結果用時:" + str((t4-t3))) r = 0 for i in range(len(test_predict)): if test_predict[i] == None: # 在樹的某一個分支處沒有其對應的特征值 test_predict[i] = 10 # 最終結果是不匹配,但是由于需要比較,所以得將None變成數字,不存在10這個手寫數字 else: if test_predict[i] == test_labels[i]: r = r + 1 score = float(r)/float(len(test_predict)) print("The accruacy score is %f" % score)

參考鏈接:

1.https://github.com/Dod-o/Statistical-Learning-Method_Code

2.https://www.cnblogs.com/kuaizifeng/p/9110157.html

3.https://blog.csdn.net/thxiong1234/article/details/79920526

我在這里重新寫一遍只是為了整理自己學過的東西并加深自己的理解,方便以后回顧復習,對于初學的朋友,建議直接閱讀以上的鏈接,

 

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/117872.html

標籤:其他

上一篇:查找演算法

下一篇:LeetCode刷題--1.兩數之和(簡單)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more