機器學習之 決策樹(Decision Tree)python實現

  1. 機器學習 之線性迴歸
  2. 機器學習 之邏輯迴歸及python實現
  3. 機器學習項目實戰 交易數據異常檢測
  4. 機器學習之 決策樹(Decision Tree)
  5. 機器學習之 決策樹(Decision Tree)python實現
  6. 機器學習之 PCA(主成分分析)
  7. 機器學習之 特徵工程
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from math import log
複製代碼

咱們使用西瓜書中的一個數據集,來進行咱們的決策樹的創建python

data = pd.read_csv("decision_tree_data3.txt",names=['編號','色澤','根蒂','敲聲','紋理','臍部','觸感','密度','含糖率','好瓜' ])
data.head()
複製代碼
編號 色澤 根蒂 敲聲 紋理 臍部 觸感 密度 含糖率 好瓜
0 1 青綠 蜷縮 濁響 清晰 凹陷 硬滑 0.697 0.460
1 2 烏黑 蜷縮 沉悶 清晰 凹陷 硬滑 0.774 0.376
2 3 烏黑 蜷縮 濁響 清晰 凹陷 硬滑 0.634 0.264
3 4 青綠 蜷縮 沉悶 清晰 凹陷 硬滑 0.608 0.318
4 5 淺白 蜷縮 濁響 清晰 凹陷 硬滑 0.556 0.215

首先,咱們須要將數據集作下處理,將對應文字轉換成離散型數據算法

# def initdata_feature(data):
# len_columns = data.shape[1]
# data_columns = data.columns
# for i in range(len_columns):
# if(i>0 and i<len_columns-3):
# str_values = data.iloc[:,i].unique()
# for j in range(len(str_values)):
# data.loc[data[data_columns[i]]==str_values[j],data_columns[i]] = j
def initdata_y(data):
    data.loc[data.好瓜 == '是 ','好瓜'] = 1
    data.loc[data.好瓜 == '否 ','好瓜'] = 0
複製代碼

測試下看看app

# initdata_feature(data)
initdata_y(data)
data
複製代碼
編號 色澤 根蒂 敲聲 紋理 臍部 觸感 密度 含糖率 好瓜
0 1 青綠 蜷縮 濁響 清晰 凹陷 硬滑 0.697 0.460 1
1 2 烏黑 蜷縮 沉悶 清晰 凹陷 硬滑 0.774 0.376 1
2 3 烏黑 蜷縮 濁響 清晰 凹陷 硬滑 0.634 0.264 1
3 4 青綠 蜷縮 沉悶 清晰 凹陷 硬滑 0.608 0.318 1
4 5 淺白 蜷縮 濁響 清晰 凹陷 硬滑 0.556 0.215 1
5 6 青綠 稍蜷 濁響 清晰 稍凹 軟粘 0.403 0.237 1
6 7 烏黑 稍蜷 濁響 稍糊 稍凹 軟粘 0.481 0.149 1
7 8 烏黑 稍蜷 濁響 清晰 稍凹 硬滑 0.437 0.211 1
8 9 烏黑 稍蜷 沉悶 稍糊 稍凹 硬滑 0.666 0.091 0
9 10 青綠 硬挺 清脆 清晰 平坦 軟粘 0.243 0.267 0
10 11 淺白 硬挺 清脆 模糊 平坦 硬滑 0.245 0.057 0
11 12 淺白 蜷縮 濁響 模糊 平坦 軟粘 0.343 0.099 0
12 13 青綠 稍蜷 濁響 稍糊 凹陷 硬滑 0.639 0.161 0
13 14 淺白 稍蜷 沉悶 稍糊 凹陷 硬滑 0.657 0.198 0
14 15 烏黑 稍蜷 濁響 清晰 稍凹 軟粘 0.360 0.370 0
15 16 淺白 蜷縮 濁響 模糊 平坦 硬滑 0.593 0.042 0
16 17 青綠 蜷縮 沉悶 稍糊 稍凹 硬滑 0.719 0.103 0

先把編號那個無用的特徵去掉機器學習

data = data.drop('編號', axis = 1)
data
複製代碼
色澤 根蒂 敲聲 紋理 臍部 觸感 密度 含糖率 好瓜
0 青綠 蜷縮 濁響 清晰 凹陷 硬滑 0.697 0.460 1
1 烏黑 蜷縮 沉悶 清晰 凹陷 硬滑 0.774 0.376 1
2 烏黑 蜷縮 濁響 清晰 凹陷 硬滑 0.634 0.264 1
3 青綠 蜷縮 沉悶 清晰 凹陷 硬滑 0.608 0.318 1
4 淺白 蜷縮 濁響 清晰 凹陷 硬滑 0.556 0.215 1
5 青綠 稍蜷 濁響 清晰 稍凹 軟粘 0.403 0.237 1
6 烏黑 稍蜷 濁響 稍糊 稍凹 軟粘 0.481 0.149 1
7 烏黑 稍蜷 濁響 清晰 稍凹 硬滑 0.437 0.211 1
8 烏黑 稍蜷 沉悶 稍糊 稍凹 硬滑 0.666 0.091 0
9 青綠 硬挺 清脆 清晰 平坦 軟粘 0.243 0.267 0
10 淺白 硬挺 清脆 模糊 平坦 硬滑 0.245 0.057 0
11 淺白 蜷縮 濁響 模糊 平坦 軟粘 0.343 0.099 0
12 青綠 稍蜷 濁響 稍糊 凹陷 硬滑 0.639 0.161 0
13 淺白 稍蜷 沉悶 稍糊 凹陷 硬滑 0.657 0.198 0
14 烏黑 稍蜷 濁響 清晰 稍凹 軟粘 0.360 0.370 0
15 淺白 蜷縮 濁響 模糊 平坦 硬滑 0.593 0.042 0
16 青綠 蜷縮 沉悶 稍糊 稍凹 硬滑 0.719 0.103 0

下面就開始實現決策樹算法,上篇文章已經知道,要根據樣本集創建一棵決策樹,具體算法流程以下: post

下面咱們來分模塊進行實現。學習

首先,來看下給定數據集的信息熵的求解測試

#求對應數據集的信息熵
def getInfoEntropy(data):
    #print('################################')
    #print(data)
    count_class = pd.value_counts(data.iloc[:,-1], sort=True)  #根據輸出值,統計不一樣樣本個數
    #print(count_class)
    data_count = len(data.iloc[:,-1])
    #print(data_count)
    Entropy = 0.0
    for i in range(len(count_class)):
        p = count_class.iloc[i]/data_count
        Entropy = Entropy + (-p * log(p,2))
    #print('當前數據集的信息熵爲:',Entropy)
    return Entropy
複製代碼

測試下看看,求取下整個樣本集的信息熵spa

getInfoEntropy(data)
複製代碼
0.9975025463691153
複製代碼

下來咱們實現下,根據對應特徵,劃分數據。須要分兩種狀況3d

  1. 離散型特徵,直接根據離散的相應類別進行劃分
  2. 連續型數據,須要參照數據離散化,選出最優的劃分值。具體原理可查看上篇文章中的連續型特徵處理

下面來看下具體代碼實現code

#離散型數據劃分
def split_data(data, column):
    splt_datas = pd.Series()   #將劃分的多個數據集保存在Series中
    str_values = data.iloc[:,column].unique()  #獲取當前數據集中,對應特徵的全部類別
    for i in range(len(str_values)):   #遍歷對應類別,找出類別所對應的數據集
        df = data.loc[data.iloc[:,column] == str_values[i]]
# print(df)
        splt_datas[str(i)] = df
    return splt_datas


#連續型數據劃分
#返回劃分後的左右兩個數據集以及所對應的最優劃分點,還有以此劃分點進行劃分數據後,對應的信息熵
def split_continuous(data,column):
    splt_datas = pd.Series()
    series_data_sort = data.iloc[:,column].sort_values()  #對應對應連續型特徵的在當前數據集中的全部值,進行從小到大排序
    split_values = []   #建立一個list,用於存儲全部的劃分點
# print(series_data_sort)
    for i in range(len(series_data_sort)-1):    #求得全部劃分點
        split_values.append((series_data_sort.iloc[i] + series_data_sort.iloc[i+1])/2)  # 注意,這塊不能用series_data_sort[i]
    best_split_value = 0.    #所要找出的最佳劃分點
    minInfoGain = 100.             
# print(split_values)
    for i in range(len(split_values)):   #遍歷全部劃分點
       # print('split_values[i]==',split_values[i])
        #根據對應劃分點,將數據集劃分爲左右兩個數據集(即二分)
        left_data = data.loc[data.iloc[:,column]<=split_values[i]]
        right_data = data.loc[data.iloc[:,column]>split_values[i]]
        #求得對應信息熵
        InfoGain = len(left_data)/len(data) * getInfoEntropy(left_data) + len(right_data)/len(data) * getInfoEntropy(right_data)
        #print('InfoGain====',InfoGain)
        if(InfoGain < minInfoGain):   #找出最小的信息熵
            minInfoGain = InfoGain
            best_split_value = split_values[i]
    left_data = data.loc[data.iloc[:,column]<=best_split_value]
    right_data = data.loc[data.iloc[:,column]>best_split_value]
    series = pd.Series()
    series['0'] = left_data
    series['1'] = right_data
    return series,best_split_value,minInfoGain
複製代碼

測試下看看

seris = split_data(data,0)
for i in range(len(seris)):
    print (seris.iloc[i])
複製代碼
色澤  根蒂  敲聲  紋理  臍部  觸感     密度    含糖率  好瓜
0   青綠  蜷縮  濁響  清晰  凹陷  硬滑  0.697  0.460   1
3   青綠  蜷縮  沉悶  清晰  凹陷  硬滑  0.608  0.318   1
5   青綠  稍蜷  濁響  清晰  稍凹  軟粘  0.403  0.237   1
9   青綠  硬挺  清脆  清晰  平坦  軟粘  0.243  0.267   0
12  青綠  稍蜷  濁響  稍糊  凹陷  硬滑  0.639  0.161   0
16  青綠  蜷縮  沉悶  稍糊  稍凹  硬滑  0.719  0.103   0
    色澤  根蒂  敲聲  紋理  臍部  觸感     密度    含糖率  好瓜
1   烏黑  蜷縮  沉悶  清晰  凹陷  硬滑  0.774  0.376   1
2   烏黑  蜷縮  濁響  清晰  凹陷  硬滑  0.634  0.264   1
6   烏黑  稍蜷  濁響  稍糊  稍凹  軟粘  0.481  0.149   1
7   烏黑  稍蜷  濁響  清晰  稍凹  硬滑  0.437  0.211   1
8   烏黑  稍蜷  沉悶  稍糊  稍凹  硬滑  0.666  0.091   0
14  烏黑  稍蜷  濁響  清晰  稍凹  軟粘  0.360  0.370   0
    色澤  根蒂  敲聲  紋理  臍部  觸感     密度    含糖率  好瓜
4   淺白  蜷縮  濁響  清晰  凹陷  硬滑  0.556  0.215   1
10  淺白  硬挺  清脆  模糊  平坦  硬滑  0.245  0.057   0
11  淺白  蜷縮  濁響  模糊  平坦  軟粘  0.343  0.099   0
13  淺白  稍蜷  沉悶  稍糊  凹陷  硬滑  0.657  0.198   0
15  淺白  蜷縮  濁響  模糊  平坦  硬滑  0.593  0.042   0
複製代碼
series,best_split_value,minInfoGain  = split_continuous(data,6)
for i in range(len(series)):
    print (series.iloc[i])
複製代碼
色澤  根蒂  敲聲  紋理  臍部  觸感     密度    含糖率  好瓜
9   青綠  硬挺  清脆  清晰  平坦  軟粘  0.243  0.267   0
10  淺白  硬挺  清脆  模糊  平坦  硬滑  0.245  0.057   0
11  淺白  蜷縮  濁響  模糊  平坦  軟粘  0.343  0.099   0
14  烏黑  稍蜷  濁響  清晰  稍凹  軟粘  0.360  0.370   0
    色澤  根蒂  敲聲  紋理  臍部  觸感     密度    含糖率  好瓜
0   青綠  蜷縮  濁響  清晰  凹陷  硬滑  0.697  0.460   1
1   烏黑  蜷縮  沉悶  清晰  凹陷  硬滑  0.774  0.376   1
2   烏黑  蜷縮  濁響  清晰  凹陷  硬滑  0.634  0.264   1
3   青綠  蜷縮  沉悶  清晰  凹陷  硬滑  0.608  0.318   1
4   淺白  蜷縮  濁響  清晰  凹陷  硬滑  0.556  0.215   1
5   青綠  稍蜷  濁響  清晰  稍凹  軟粘  0.403  0.237   1
6   烏黑  稍蜷  濁響  稍糊  稍凹  軟粘  0.481  0.149   1
7   烏黑  稍蜷  濁響  清晰  稍凹  硬滑  0.437  0.211   1
8   烏黑  稍蜷  沉悶  稍糊  稍凹  硬滑  0.666  0.091   0
12  青綠  稍蜷  濁響  稍糊  凹陷  硬滑  0.639  0.161   0
13  淺白  稍蜷  沉悶  稍糊  凹陷  硬滑  0.657  0.198   0
15  淺白  蜷縮  濁響  模糊  平坦  硬滑  0.593  0.042   0
16  青綠  蜷縮  沉悶  稍糊  稍凹  硬滑  0.719  0.103   0
複製代碼

接下來,咱們要作的就是,給定一個數據集,咱們須要求得最優的劃分特徵,先來來看下代碼實現

# 查找當前數據集data 的 最優劃分特徵。返回對應最優特徵在數據集data中的索引
def find_best_feature(data):
    best_feature_index = 0    #用來保存最優劃分特徵的索引
    minInfoGain = 100.      #保存信息增益
    samplenumber = len(data)   #當前數據集的個數
    best_split_value_return = 0.  #若是最優劃分特徵是個連續類型的,則還須要保存對應的連續特徵的最優劃分點
    best_split_value = 0.
    best_Series = pd.Series()
    for i in range(data.shape[1]-1):    #遍歷數據集的全部特徵
        InfoGain = 0.
        series = pd.Series()
        if(i < data.shape[1]-3):    #離散型屬性
            series = split_data(data, i)   #根據特徵劃分數據,將劃分的多個數據集(DataFrame)保存在一個Series中返回 
            for j in range(len(series)):
                df = series[j]
                InfoGain = InfoGain +len(df)/samplenumber *(getInfoEntropy(df))
# print('InfoGain==',InfoGain,'----i=',i)
        else:                      #連續型屬性
            series,best_split_value, InfoGain = split_continuous(data,i)
# print('InfoGain==',InfoGain,'----i=',i)
        if(InfoGain < minInfoGain):
            minInfoGain = InfoGain
            InfoGain = 0.0
            best_feature_index = i
            best_Series = series
            if(i >= data.shape[1]-3):
                best_split_value_return = best_split_value
     
    return data.columns[best_feature_index],best_Series,best_split_value_return

複製代碼

測試下看看

find_best_feature(data)
複製代碼
('紋理', 0        色澤  根蒂  敲聲  紋理  臍部  觸感     密度    含糖率  好瓜
 0...
 1        色澤  根蒂  敲聲  紋理  臍部  觸感     密度    含糖率  好瓜
 6...
 2        色澤  根蒂  敲聲  紋理  臍部  觸感     密度    含糖率  好瓜
 1...
 dtype: object, 0.0)
複製代碼

接下來就要實現決策樹的構建了

#建立樹模型
def creat_Tree(data):
    y_values = data.iloc[:,-1].unique()   #獲得當前數據集的y的類別
    if(len(y_values) == 1):             #若是隻剩下一個類別,說明已是純淨的數據,不須要再分,直接返回
        return y_values[0]
    flag = 0
    for i in range(data.shape[1]-1):   #當前節點中的全部樣本在當前所剩屬性集中取值相同,則直接返回當前數據集中類別樣本多的那個類別
        if(len(data.iloc[:,i].unique()) != 1):
            flag = 1
            break
    if(flag == 0):
        value_count = pd.value_counts(data.iloc[:,-1])
        return value_count.index[0]
    best_feature, best_Series,best_split_value = find_best_feature(data)  #尋找最優特徵,返回最優特徵,劃分後的數據集,已經若是是連續型特徵,還須要劃分點
    Tree = {best_feature:{}}    #用字典來模擬樹
    for j in range(len(best_Series)):    #遍歷劃分後的數據集
        split_data = best_Series.iloc[j]
        value = ''
        if(best_split_value == 0.0):    #說明是離散型特徵
            value = split_data.loc[:,best_feature].unique()[0]   #獲取對應劃分的特徵中,對應的特徵類別
            split_data = split_data.drop(best_feature, axis = 1) #離散型型特徵,用完後須要刪除
        else:                          #不然,說明是連續型特徵
            if(j == 0):
                value = '<='+str(best_split_value)
            else:
                value = '>'+str(best_split_value)
        Tree[best_feature][value] = creat_Tree(split_data)   #採用遞歸思想,繼續構建
    return Tree
    
複製代碼
Tree = creat_Tree(data)
Tree
複製代碼
{'紋理': {'模糊': 0,
  '清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}},
  '稍糊': {'觸感': {'硬滑': 0, '軟粘': 1}}}}
複製代碼

接下來,來實現下,使用訓練出來的決策樹,對新的數據進行分類

#預測一個樣本
def classification_one(Tree, data):
    print(Tree)
    first_key = list(Tree.keys())[0]  #獲取根節點的key
    first_value = Tree[first_key]     #獲取根節點對應的value
    result = -1   #初始化,用來保存當前節點的結果
    if('<' in list(first_value.keys())[0]):     #連續型特徵
        #解釋下下面兩行代碼,裏面的 list(first_value.keys())[0] 獲取來的就是‘<=0.38...’這種格式,須要從這個裏面解析出0.38...這個分割點
        left_key =  list(first_value.keys())[0]  #'<=分割點'
        right_key =  list(first_value.keys())[1] #'>分割點'
        split_poit = float(''.join(list(left_key)[2:]))  # '分割點'
        if(data[first_key] <= split_poit):   #若是屬於左分支
            if(isinstance(first_value[left_key], dict)):   #判斷是不是葉子節點,若是對應的value仍是一個dict字典,則說明是個非葉子節點,繼續遞歸
                result = classification_one(first_value[left_key],data)
            else:                                         #若是是葉子節點,返回結果值
                result = first_value[left_key]
        else:                              #若是屬於左分支
            if(isinstance(first_value[right_key], dict)):
                result = classification_one(first_value[right_key],data)
            else:
                result = first_value[right_key]
    else:                        #離散型特徵
        if(isinstance(first_value[data[first_key]], dict)):
            result = classification_one(first_value[data[first_key]],data)
        else:
            result = first_value[data[first_key]]
    return result

#預測多個樣本
def classification_more(Tree, data):
    result_list = []
    for i in range(data.shape[0]):
        result = classification_one(Tree, data.iloc[i])
        result_list.append(result)
    return result_list
複製代碼
classification_more(Tree,data)
複製代碼
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'觸感': {'軟粘': 1, '硬滑': 0}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'觸感': {'軟粘': 1, '硬滑': 0}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'觸感': {'軟粘': 1, '硬滑': 0}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'觸感': {'軟粘': 1, '硬滑': 0}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'紋理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'觸感': {'軟粘': 1, '硬滑': 0}}, '模糊': 0}}
{'觸感': {'軟粘': 1, '硬滑': 0}}





[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
複製代碼

咱們仍是使用的上面的那個數據集用來驗證,能夠看到,已經徹底擬合了訓練集,

可是,這樣真的好嗎?正如上篇文章說的,決策樹若是不進行剪枝的話,確定最後會一直分下去,直到所分的各個數據集徹底是純淨的,這樣,很是容易致使過擬合現象。因此,還須要進行剪枝操做。具體代碼這塊不演示了,只要掌握了整個決策樹構建的原理,實現起來也很簡單。

上面,演示的只是ID3算法的相關實現,還有決策的其餘算法,例如C4.5決策樹算法,主要區別就是最優劃分特徵的選擇標準不一樣。流程基本都是一致的。

歡迎關注個人我的公衆號 AI計算機視覺工坊,本公衆號不按期推送機器學習,深度學習,計算機視覺等相關文章,歡迎你們和我一塊兒學習,交流。

相關文章
相關標籤/搜索