python學習day-11 機器學習-監督學習-分類-決策樹&臨近取樣KNN


一、Dtree理論部分

0. 機器學習中分類和預測算法的評估:
  • 准確率
  • 速度
  • 強壯行   當有噪聲或者幾個值缺失時,還能夠進行評估
  • 可規模性    當數據從指數增長時,變得非常的,算法能夠繼續工作
  • 可解釋性

1. 什么是決策樹/判定樹(decision tree)?

     
     判定樹是一個類似於流程圖的樹結構:其中,每個內部結點表示在一個屬性上的測試,每個分支代表一個屬性輸出,而每個樹葉結點代表類或類分布。樹的最頂層是根結點。
 
 
2.  機器學習中分類方法中的一個重要算法
 
3.  構造決策樹的基本算法                     
                                                           分支                   根結點                結點
 
 
 
 
     3.1 熵(entropy)概念:
 
          信息和抽象,如何度量?
          1948年,香農提出了 ”信息熵(entropy)“的概念
          一條信息的信息量大小和它的不確定性有直接的關系,要搞清楚一件非常非常不確定的事情,或者          
          是我們一無所知的事情,需要了解大量信息==>信息量的度量就等於不確定性的多少
          比特(bit)來衡量信息的多少
 
          
 
          變量的不確定性越大,熵也就越大
          
 
     3.1 決策樹歸納算法 (ID3)
          選擇屬性判斷結點
          信息獲取量(Information Gain):Gain(A) = Info(D) - Infor_A(D)
          通過A來作為節點分類獲取了多少信息
 
 
           類似,Gain(income) = 0.029, Gain(student) = 0.151, Gain(credit_rating)=0.048
 
          所以,選擇age作為第一個根節點
 
          重復。。。一直算下去
 
 
          算法:
  • 樹以代表訓練樣本的單個結點開始
  • 如果樣本都在同一個類,則該結點成為樹葉,並用該類標號
  • 否則,算法使用稱為信息增益的基於熵的度量作為啟發信息,選擇能夠最好地將樣本分類的屬性(步驟6)。該屬性成為該結點的“測試”或“判定”屬性在算法的該版本中,
  • 所有的屬性都是分類的,即離散值。連續屬性必須離散化。
  • 對測試屬性的每個已知的值,創建一個分枝,並據此划分樣本
  • 算法使用同樣的過程,遞歸地形成每個划分上的樣本判定樹。一旦一個屬性出現在一個結點上,就不必該結點的任何后代上考慮它
  • 遞歸划分步驟僅當下列條件之一成立停止:
  • (a) 給定結點的所有樣本屬於同一類
  • (b) 沒有剩余屬性可以用來進一步划分樣本在此情況下,使用多數表決
  • 這涉及將給定的結點轉換成樹葉,並用樣本中的多數所在的類標記它。替換地,可以存放結
  • 點樣本的類分布。
  • (c) 分枝
  • test_attribute = a i 沒有樣本在這種情況下,以 samples 中的多數類
  • 創建一個樹葉
 
     3.1 其他算法:
               C4.5:  Quinlan
               Classification and Regression Trees (CART): (L. Breiman, J. Friedman, R. Olshen, C. Stone)
               共同點:都是貪心算法,自上而下(Top-down approach)
               區別:屬性選擇度量方法不同: C4.5 (gain ratio), CART(gini index), ID3 (Information Gain)
 
     3.2 如何處理連續性變量的屬性? 
 
4. 樹剪枝葉 (避免overfitting)
     4.1 先剪枝
     4.2 后剪枝
5. 決策樹的優點:
     直觀,便於理解,小規模數據集有效     
6. 決策樹的缺點:
     處理連續變量不好
     類別較多時,錯誤增加的比較快
     可規模性一般

 

二、決策樹的應用---代碼應用

1.首先利用python里機器學習的庫   scikit-learn

      1.1: 特性:
簡單高效的數據挖掘和機器學習分析
對所有用戶開放,根據不同需求高度可重用性
基於Numpy, SciPy和matplotlib
開源,商用級別:獲得 BSD許可 
     1.2 覆蓋問題領域:
          分類(classification), 回歸(regression), 聚類(clustering), 降維(dimensionality reduction)
          模型選擇(model selection), 預處理(preprocessing)
2,安裝
     使用用scikit-learn
     安裝scikit-learn: pip, easy_install, windows installer
     安裝必要package:numpy, SciPy和matplotlib, 可使用Anaconda (包含numpy, scipy等科學計算常用
     package)
3.在運行程序的時候我會出現
AttributeError: '_csv.reader' object has no attribute 'next'
 
from sklearn.feature_extraction import DictVectorizer
import csv
from sklearn import tree
from sklearn import preprocessing
from sklearn.externals.six import StringIO

# Read in the csv file and put features into list of dict and list of class label
allElectronicsData = open(r'C:\Users\222\PycharmProjects\Dtree\AllElectronics.csv', 'rb')
reader = csv.reader(allElectronicsData)
headers = reader.next()
解決方案

# Read in the csv file and put features into list of dict and list of class label
allElectronicsData = open(r'C:\Users\222\PycharmProjects\Dtree\AllElectronics.csv', 'rt')
reader = csv.reader(allElectronicsData)
headers = next(reader)

1.For version 3.2 and above   2.Change:reader.next()      To: next(reader)      3.then I get another error:

_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)

4.Edit: Figured it out needed to :  change rb to rt

來自   https://blog.csdn.net/qing101hua/article/details/77002444   

4.而我又遇到了問題

ValueError: Expected 2D array, got 1D array instead:

根據提示找到問題所在為 調用svc.predict()處出現問題 
查看svc.predict的使用方法 
print(help(svc.predict))
修改前 
test_prediction = svc.predict(hog_features.reshape) 
修改后 
test_prediction = svc.predict(hog_features.reshape(1,-1)) 

執行后錯誤消失

5.決策樹的代碼

from sklearn.feature_extraction import DictVectorizer #導入模塊 import csv from sklearn import tree from sklearn import preprocessing from sklearn.externals.six import StringIO # Read in the csv file and put features into list of dict and list of class label allElectronicsData = open(r'C:\Users\222\PycharmProjects\Dtree\AllElectronics.csv', 'rt') #打開文件 reader = csv.reader(allElectronicsData) #讀取文件 headers = next(reader) #將第一行的標題讀取 print(headers) featureList = [] #特征列表和標簽列表 labelList = [] for row in reader: #遍歷第一列到倒數第二列 生成字典 labelList.append(row[len(row)-1]) rowDict = {} for i in range(1, len(row)-1): rowDict[headers[i]] = row[i] featureList.append(rowDict) print(featureList) #形成一個大字典 方便后續進行數據轉換 # Vetorize features vec = DictVectorizer() dummyX = vec.fit_transform(featureList) .toarray() #轉換的特征數據順序與初始數據對上 01010011。。。。 print("dummyX: " + str(dummyX)) print(vec.get_feature_names()) print("labelList: " + str(labelList)) #標簽 # vectorize class labels lb = preprocessing.LabelBinarizer() #最終y 的結果 dummyY = lb.fit_transform(labelList) print("dummyY: " + str(dummyY)) # Using decision tree for classification # clf = tree.DecisionTreeClassifier() clf = tree.DecisionTreeClassifier(criterion='entropy')#利用庫里的算法對x y 處理 clf = clf.fit(dummyX, dummyY) print("clf: " + str(clf)) # Visualize model(graphviz要自己下載 ) with open("allElectronicInformationGainOri.dot", 'w') as f: f = tree.export_graphviz(clf, feature_names=vec.get_feature_names(), out_file=f) oneRowX = dummyX[0, :] print("oneRowX: " + str(oneRowX)) newRowX = oneRowX newRowX[0] = 0 newRowX[2] = 1 print("newRowX: " + str(newRowX)) predictedY = clf.predict(newRowX.reshape(1,-1)) print("predictedY: " + str(predictedY))

 結果

6.需要安裝graphviz 是一個可視化的軟件

轉化dot文件至pdf可視化決策樹:dot -Tpdf iris.dot -o outpu.pdf

7.Anaconda去官網下載這個,並添加到環境變量中,和加入到pydev里選取編譯器

 

 

KNN臨近取樣

一、理論知識

 

     1.1 Cover和Hart在1968年提出了最初的鄰近算法

 

     1.2 分類(classification)算法

 

     1.3 輸入基於實例的學習(instance-based learning), 懶惰學習(lazy learning)

2. 算法詳述

     2.1 步驟:

     為了判斷未知實例的類別,以所有已知類別的實例作為參照

     選擇參數K

     計算未知實例與所有已知實例的距離

     選擇最近K個已知實例

     根據少數服從多數的投票法則(majority-voting),讓未知實例歸類為K個最鄰近樣本中最多數的類別

     2.2 細節:關於K

     關於距離的衡量方法:

  3.2.1 Euclidean Distance 定義

              

  其他距離衡量:余弦值(cos), 相關度 (correlation), 曼哈頓距離 (Manhattan distance)

3. 算法優缺點:

     3.1 算法優點  簡單 易於理解  容易實現  通過對K的選擇可具備丟噪音數據的健壯性

     3.2 算法缺點

          x沒問題  但是y就出現問題了

          需要大量空間儲存所有已知實例

          算法復雜度高(需要比較所有已知實例與要分類的實例)

          當其樣本分布不平衡時,比如其中一類樣本過大(實例數量過多)占主導的時候,新的未知實例容易被歸類為這個主導樣本,因為這類樣本實例的數量過大,但這個新的未知實例實際並木接近目標樣本

 4. 改進版本

      考慮距離,根據距離加上權重

      比如: 1/d (d: 距離)

二、代碼

    運行程序時我出現了以下問題

1.         IndentationError:expected an indented block錯誤解決

 

Python語言是一款對縮進非常敏感的語言,給很多初學者帶來了困惑,即便是很有經驗的Python程序員,也可能陷入陷阱當中。最常見的情況是tab和空格的混用會導致錯誤,或者縮進不對,而這是用肉眼無法分別的。

在編譯時會出現這樣的錯IndentationError:expected an indented block說明此處需要縮進,你只要在出現錯誤的那一行,按空格或Tab(但不能混用)鍵縮進就行。

 

2.      Python 中 'unicodeescape' codec can't decode bytes in position XXX: trun錯誤解決方案

類似的錯誤,原來是圖片路徑寫的 有問題,錯誤代碼如下
loadDataset('‪C:\Users\222\PycharmProjects\KNN\irisdata.txt', split, trainingset, testset)
修改為

loadDataset('‪C:\Users\\222\P\ycharmProjects\\KNN\\irisdata.txt', split, trainingset, testset)
loadDataset(r'‪C:\Users\222\PycharmProjects\KNN\irisdata.txt', split, trainingset, testset)


loadDataset(r'‪C:/Users/222/PycharmProjects/KNN/irisdata.txt', split, trainingset, testset)

                                                                                                                              
3.       AttributeError: 'dict' object has no attribute 'iteritems'
Python3.5中:iteritems變為items   


4.此csv文件並非二進制文件, 只是一個文本文件。就要將rb改為rt
with open(filename, 'rt') as csvfile:

with open(filename, 'rb') as csvfile:


代碼實現

import csv import random import math import operator #將要用的數據集裝載進來 def loadDataset(filename, split, trainingSet = [], testSet = []): #文件名,分割第幾行,訓練集,測試集 with open(filename, 'rt') as csvfile: #讀取文件所有行數 lines = csv.reader(csvfile) #轉化為列表 dataset = list(lines) #遍歷 for x in range(len(dataset)-1): for y in range(4): dataset[x][y] = float(dataset[x][y]) if random.random() < split: #出現一個隨機的行數如果小於分割的位置 就把它加入訓練集,否則就加到測試集  trainingSet.append(dataset[x]) else: testSet.append(dataset[x]) #計算距離 def euclideanDistance(instance1, instance2, length): #輸入兩個實例和維度,返回距離值 distance = 0 for x in range(length): distance += pow((instance1[x]-instance2[x]), 2) return math.sqrt(distance) #返回最近的k個鄰居 def getNeighbors(trainingSet, testInstance, k): distances = [] length = len(testInstance)-1 for x in range(len(trainingSet)): #testinstance dist = euclideanDistance(testInstance, trainingSet[x], length) distances.append((trainingSet[x], dist)) #distances.append(dist) distances.sort(key=operator.itemgetter(1)) #從小到大進行排序 neighbors = [] for x in range(k): neighbors.append(distances[x][0]) return neighbors #根據少數服從多數的法則 def getResponse(neighbors): classVotes = {} for x in range(len(neighbors)): response = neighbors[x][-1] if response in classVotes: classVotes[response] += 1 else: classVotes[response] = 1 sortedVotes = sorted(classVotes.items(), key=operator.itemgetter(1), reverse=True) #按降序排列 return sortedVotes[0][0] #准確率是多少 def getAccuracy(testSet, predictions): correct = 0 for x in range(len(testSet)): if testSet[x][-1] == predictions[x]: correct += 1 return (correct/float(len(testSet)))*100.0 def main(): #prepare data trainingSet = [] testSet = [] split = 0.67 loadDataset('C:/Users/王孝義/PycharmProjects/KNN/irisdata.txt', split, trainingSet, testSet) print ('Train set: ' + repr(len(trainingSet))) print ('Test set: ' + repr(len(testSet))) #generate predictions predictions = [] k = 3 for x in range(len(testSet)): # trainingsettrainingSet[x] neighbors = getNeighbors(trainingSet, testSet[x], k) result = getResponse(neighbors) predictions.append(result) print ('>predicted=' + repr(result) + ', actual=' + repr(testSet[x][-1])) print ('predictions: ' + repr(predictions)) accuracy = getAccuracy(testSet, predictions) print('Accuracy: ' + repr(accuracy) + '%') if __name__ == '__main__': main()

 


輸出結果

 

 

 

 

 

 

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com