除了FastJson,你也應該了解一下Jackson(一)

在上月末的時候收到一條關於fastjson安全漏洞的消息,突然想到先前好像已經有好多次這樣的事件了(在fastjson上面)。關於安全方面,雖然中槍的機率微小,但是在這個信息越來越複雜的時代,安全性也變得越來越重要,就像DevSecOps的誕生,在軟件交付的整個價值流中我們也需要注重安全這方面。當然我們現在不談關於FastJson的優劣,因為我們本文的目標是讓大家了解和掌握Jackson。

概覽

Jackson是一個非常流行和高效的基於Java的庫,它可以序列化java對象或將java對象映射到JSON,反之亦然。當然除了Jackson,在Java中同類型的優秀的庫也有很多,比如:

  • Gson
  • json-io
  • Genson

關於哪一個最好或者哪一個最流行,沒有明確的答案。技術的種類繁多,每個人對與不同技術的態度也不一樣。言歸正傳,文章主要還是討論Jackson的。本文主要講解我們處理Json中最常見的兩個操作:

  • 將Java對象序列化為JSON
  • JSON字符串反序列化為Java對象

引入依賴

由於在Spring/SpringBoot中很多組件已經自帶了Jackson庫,所以很多情況下不需要手動引入Jackson的依賴。

手動引入依賴:

<dependency> 
  <groupId>com.fasterxml.jackson.core</groupId> 
  <artifactId>jackson-databind</artifactId> 
  <version>2.9.8</version>
</dependency>

這個依賴關係還將傳遞地向類路徑添加以下庫:

  1. jackson-annotations-2.9.8.jar
  2. jackson-core-2.9.8.jar
  3. jackson-databind-2.9.8.jar

JavaObject to Json

ObjectMapper

ObjectMapper是一個映射器(或數據綁定器或編解碼器),提供了在Java對象(bean的實例)和JSON之間進行轉換的功能。

首先定義一個簡單的Java類

public class Car {
    private String color;
    private String type;
    // standard getters setters
}

將Java對象轉換成Json

我們使用ObjectMapper的writeValue相關Api來對Java對象進行序列化操作

ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("blue","c1");
System.out.println(objectMapper.writeValueAsString(car));

此時輸出

{"color":"blue","type":"c1"}

更多

ObjectMapper的writeValue相關Api還提供了很多便利的Json序列化操作方法,比如:將對象序列化成Json字節數組的writeValueAsBytes()方法、自定義輸出源的writeValue()方法…

ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("blue","c1");
objectMapper.writeValue(new File("./xxx.txt"),car);

運行上述代碼,Java對象的序列化Json將被輸出到xxx.txt文件。

Json to JavaObject

將Json String轉換成Java Object

ObjectMapper objectMapper = new ObjectMapper();
String json = "{\"color\":\"blue\",\"type\":\"c1\"}";
Car car = objectMapper.readValue(json, Car.class);

readValue()方法也接受其他形式的輸入,比如包含JSON字符串的文件:

ObjectMapper objectMapper = new ObjectMapper();
Car car = objectMapper.readValue(new File("./xxx.txt"), Car.class);
System.out.println(car);

JSON to Jackson JsonNode

JsonNode

一個JSON可以被解析成一個JsonNode對象,用來從一個特定的節點檢索數據.

使用readTree()方法,我們可以將Json字符串轉換成JsonNode

ObjectMapper objectMapper = new ObjectMapper();
String json = "{ \"color\" : \"Black\", \"type\" : \"FIAT\" }";
JsonNode jsonNode = objectMapper.readTree(json);
System.out.println(jsonNode.findValue("type").asText());
// 打印出“FAIT”

JSONArrayString to JavaList

ObjectMapper objectMapper = new ObjectMapper();
String jsonCarArray =
    "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : 3. \"Red\", \"type\" : \"FIAT\" }]";
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>() {});

JSONString to JavaMap

ObjectMapper objectMapper = new ObjectMapper();
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Map<String, Object> map = objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {
});

Jackson庫最大的優點之一是高度可定製的序列化和反序列化過程。接下來將介紹一些高級特性,其中輸入或輸出JSON響應可以與生成或使用響應的對象不同。

配置序列化和反序列化特性

String jsonString = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" :\"1970\" }";

假設使用如上json字符串來反序列化成Java對象,按照默認解析過程將導致UnrecognizedPropertyException異常,因為其中存在Car類中未包含的新字段year。

通過配置序列化和反序列化特性來解決此問題:

ObjectMapper objectMapper = new ObjectMapper();
String jsonString = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" :\"1970\" }";
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Car car = objectMapper.readValue(jsonString, Car.class);

如上,我們在ObjectMapper中配置了DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES=false,從而實現忽略新的字段。

類似:另一個選項FAIL_ON_NULL_FOR_PRIMITIVES,它定義了是否允許原始值的空值;FAIL_ON_NUMBERS_FOR_ENUM控制是否允許enum值被序列化/反序列化為数字……

自定義序列化器或反序列化器

自定義序列化器

public static class CustomCarSerializer extends StdSerializer<Car> {
    public CustomCarSerializer() {
        this(null);
    }

    public CustomCarSerializer(Class<Car> t) {
        super(t);
    }

    @Override
    public void serialize(Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) throws IOException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("car_brand", car.getType());
        jsonGenerator.writeEndObject();
    }
}

如上,通過繼承StdSerializer類,我們實現了一個自定義的序列化器。

使用自定義的序列化器:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("CustomCarSerializer", new Version(1, 0, 0, null, null, null));
module.addSerializer(Car.class, new CustomCarSerializer());
mapper.registerModule(module);
Car car = new Car("yellow", "enault");
System.out.println(mapper.writeValueAsString(car));
//輸出{"car_brand":"enault"}

自定義反序列化器

public static class CustomCarDeserializer extends StdDeserializer<Car> {

        public CustomCarDeserializer() {
            this(null);
        }

        protected CustomCarDeserializer(Class<?> vc) {
            super(vc);
        }

        @Override
        public Car deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            Car car = new Car();
            ObjectCodec codec = p.getCodec();
            JsonNode node = codec.readTree(p);
            // try catch block
            JsonNode colorNode = node.get("color");
            String color = colorNode.asText();
            car.setColor(color);
            return car;
        }
    }

如上,通過繼承StdDeserializer類,我們實現了一個自定義的序列化器。

使用自定義的反序列化器:

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\"}";
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null));
module.addDeserializer(Car.class, new CustomCarDeserializer());
mapper.registerModule(module);
Car car = mapper.readValue(json, Car.class);
//此時的car {color='Black', type='null'}

處理時間格式

️:此處僅展示對於Java8的LocalDate&LocalDateTime的處理

首先創建一個帶日期時間字段的Car類

public class Car {
    private String color;
    private String type;
  	@JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDateTime produceTime;
    // standard getters setters
}

自定義時間格式處理

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.findAndRegisterModules();
Car car = new Car().setColor("blue").setType("c1").setProduceTime(LocalDateTime.now());
String carAsString = objectMapper.writeValueAsString(car);
System.out.println(carAsString);
//此時輸出:{"color":"blue","type":"c1","produceTime":"2020-06-06"}

處理集合

DeserializationFeature類提供的另一個小但有用的特性是能夠從JSON數組響應生成我們想要的集合類型。

String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\"}, { \"color\" : \"Red\", \"type\" : \"FIAT\"}]";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class);

如上,我們將一個JsonArray字符串轉換成了對象數組。

我們也可以將其轉換成集合:

String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\"}, { \"color\" : \"Red\", \"type\" : \"FIAT\"}]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});

總結

Jackson是一個可靠而成熟的用於Java的JSON序列化/反序列化庫。ObjectMapper API提供了一種簡單的方法來解析和生成JSON響應對象,具有很大的靈活性。

歡迎訪問筆者博客:blog.dongxishaonian.tech

關注筆者公眾號,推送各類原創/優質技術文章 ⬇️

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

※產品缺大量曝光嗎?你需要的是一流包裝設計!

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

Kubernetes-PV和PVC的原理和實踐

一、什麼是PV和PVC?

PV的全稱是Persistent Volume,翻譯過來為持久化存儲卷,是對底層的共享存儲的一種抽象,PV由管理員進行創建和配置,主要含存儲能力、訪問模式、存儲類型、回收策略、後端存儲類型等主要信息,它和具體的底層的共享存儲技術的實現方式有關,比如NFS、Hostpath、RBD等。

PVC的全稱是: PersistenVolumeClaim (持久化卷聲明),PVC是用戶存儲的一種聲明,PVC和Pod類似,Pod是消耗節點node資源,PVC消耗的是PV資源,Pod可以請求CPU的內存,而PVC可以請求特定的存儲空間和訪問模式。

二、PV和PVC的使用場景

 

 

 配圖來自K8S權威指南第四版

 

 存儲工程師把分佈式存儲系統上的總空間劃分成一個一個小的存儲塊,K8S的集群管理員將存儲塊和PV進行一一對應,用戶通過PVC對對存儲進行申請,比如可以指定具體容量的大小,訪問模式或者存儲類型,這樣的好處是用戶不需要關心底層的存儲實現細節,只需要直接申請使用PVC即可,若申請的PVC所對應的PV不能滿足用戶的要求,不會生效,直到有合適的PV生成,PVC會自動與PV完成綁定,存儲工程師、K8S管理員,用戶之間業務解耦,靈活性更強。

 

三、創建PV

PV支持多種不同類型的存儲,如:NFS、hostpath、RBD、ICCSI,本文以hostpath為例介紹如何創建PV

第一步:現在宿主機data目錄下data/pod/volume1,volume1將作為PV對應的hostpath本地存儲的目錄

第二步:通過yaml文件創建PV

 1 [root@k8s-master zhanglei]# cat pv-hostpath.yaml  2 kind: PersistentVolume #指定為PV類型  3 apiVersion: v1  4 metadata:  5   name: pv-statefulset #指定PV的名稱  6  labels: #指定PV的標籤  7  release: stable  8 spec:  9  capacity: 10     storage: 0.1Gi #指定PV的容量 11  accessModes: 12     - ReadWriteOnce #指定PV的訪問模式,簡寫為RWO,只支持掛在1個Pod的讀和寫 13  persistentVolumeReclaimPolicy: Recycle #指定PV的回收策略,Recycle表示支持回收,回收完成后支持再次利用 14  hostPath: #指定PV的存儲類型,本文是以hostpath為例 15     path: /data/pod/volume1 #指定PV對應後端存儲hostpath的目錄

說明:

 accessModes支持多種訪問模式

1)ReadWriteOnce(RWO):讀寫權限,但是只支持掛載在1個Pod

2)ReadOnlyMany(ROX):只讀權限,支持掛載在多個Pod

3)ReadWriteMany(RW):讀寫權限,支持掛載在多個Pod上

persistentVolumeReclaimPolicy的策略,指的是如果PVC被釋放掉后,PV的處理,這裏所說的釋放,指的是用戶刪除PVC后,與PVC對應的PV會被釋放掉,PVC個PV是一一對應的關係

1)Retain,PV的數據不會清理,會保留volume,如果需要清理,需要手動進行

2)Recycle,會將數據進行清理,即 rm -rf /thevolume/*(只有 NFS 和 HostPath 支持),清理完成后,PV會呈available狀態,支持再次的bound

3)Delete,刪除存儲資源,會刪除PV及後端的存儲資源,比如刪除 AWS EBS 卷(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)

四、創建PVC

[root@k8s-master zhanglei]# cat pvc-hostpath.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mppvc-01                  # 指定PVC的名稱
  namespace: default
spec:
 accessModes: ["ReadWriteOnce"]    # 指定PVC的訪問模式
 resources:
   requests: 
     storage: 0.05Gi               # PVC申請的容量

說明:

1)PVC聲明了accessModes訪問類型為ReadWriteOnce,創建后,系統會自動去找能夠支持ReadWriteOnce訪問類型的PV,若無符合條件的PV,則不會進行綁定,

2)PVC聲明了storage的大小為0.05Gi,創建后,系統會自動去找能夠支持此容量的PV,通常PV的容量至少要大於或者等於0.05Gi才會去進行綁定

從這裏來看,對於用戶來說,即只需要聲明訪問類型、容量、另外還可通過StorageClass聲明具體的PV類型即可完成對持久化存儲卷的申請,而不需要去維護和關注後端存儲

五、查詢PV和PVC的

經過前面的步驟我們創建了PV和PVC,現在來看下兩者是否已經完成了綁定,在PV的創建已經指定了其名稱為pv-statefulset,PVC的名稱為mppvc-01

 

 

[root@k8s-master zhanglei]# kubectl get pv |grep pv-statefulset
pv-statefulset      107374182400m   RWO            Recycle          Bound    default/mppvc-01 

 

[root@k8s-master zhanglei]# kubectl get pvc |grep mppvc-01
mppvc-01                            Bound    pv-statefulset      107374182400m   RWO                           13d

可以看到pv-statefulset這個PV已經和mppvc-01的PVC進行了綁定(Bound),RWO和Recycle也是之前PV和PVC聲明的狀態,說明綁定成功


[root@k8s-master zhanglei]# kubectl describe pv pv-statefulset
Name:            pv-statefulset
Labels:          release=stable
Annotations:     pv.kubernetes.io/bound-by-controller: yes
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    
Status:          Bound
Claim:           default/mppvc-01
Reclaim Policy:  Recycle
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        107374182400m
Node Affinity:   <none>
Message:         
Source:
    Type:          HostPath (bare host directory volume)
    Path:          /data/pod/volume1
    HostPathType:  
Events:            <none>
[root@k8s-master zhanglei]# kubectl describe pvc mppvc-01
Name:          mppvc-01
Namespace:     default
StorageClass:  
Status:        Bound
Volume:        pv-statefulset
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      107374182400m
Access Modes:  RWO
VolumeMode:    Filesystem
Mounted By:    <none>
Events:        <none>

再來看下PV的詳細(describe)信息,可以看到type是hostpath類型,显示了數據卷在宿主機的/data/pod/volume1的目錄。

 

六、總結

創建PV和PVC分為二步:

第一步:創建PV,支持自定義不同的存儲大小和訪問模式(RWX,RWO)、存放路徑、後端服務server(如hostpath、或NAS盤的數據盤的掛載點)

第二步:創建PVC,綁定到PV。創建PVC的時候可以指定PVC的request storage,即申請的存儲的容量,會根據申請的storage和訪問模式自動匹配符合要求的PV

創建完PV和PVC主要是為了使用它來達到實現持久化存儲的目的,如何進行使用請看本作者後續與statufulset有關的文章,謝謝閱讀~

 

作者簡介:雲計算容器\K8S方向產品經理,學點技術,為更好地設計產品。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※推薦台中搬家公司優質服務,可到府估價

機器學習——十大數據挖掘之一的決策樹CART算法

本文始發於個人公眾號:TechFlow,原創不易,求個關注

今天是機器學習專題的第23篇文章,我們今天分享的內容是十大數據挖掘算法之一的CART算法。

CART算法全稱是Classification and regression tree,也就是分類回歸樹的意思。和之前介紹的ID3和C4.5一樣,CART算法同樣是決策樹模型的一種經典的實現。決策樹這個模型一共有三種實現方式,前面我們已經介紹了ID3和C4.5兩種,今天剛好補齊這最後一種。

算法特點

CART稱為分類回歸樹,從名字上我們也看得出來,它既能支持分類又可以支持回歸。的確如此,決策樹的確支持回歸操作,但是我們一般不會用決策樹來進行回歸。這裏面的原因很多,除了樹模型擬合能力有限效果不一定好之外,還與特徵的模式有關係,樹回歸模型受到特徵的影響非常大。這個部分我們不做太多深入,之後會在回歸樹的文章當中詳細探討。

正因為回歸樹模型效果表現都不太理想,所以CART算法實現決策樹基本都是用來做分類問題。那麼在分類問題上,它與之前的ID3算法和C4.5算法又有什麼不同呢?

主要細究起來大約有兩點,第一點是CART算法使用Gini指數而不是信息增益來作為劃分子樹的依據,第二點是CART算法每次在劃分數據的時候,固定將整份數據拆分成兩個部分,而不是多個部分。由於CART每次將數據拆分成兩個部分,所以它對於拆分的次數沒有限制,而C4.5算法對特徵進行了限制,限制了每個特徵最多只能使用一次。因為這一點,同樣CART對於剪枝的要求更高,因為不剪枝的話很有可能導致樹過度膨脹,以至於過擬合。

Gini指數

在ID3和C4.5算法當中,在拆分數據的時候用的是信息增益和信息增益比,這兩者都是基於信息熵模型。信息熵模型本身並沒有問題,也是非常常用的模型。唯一的問題是,在計算熵的時候需要涉及到log運算,相比於四則運算來說,計算log要多耗時很多

Gini指數本質上也是基於信息熵模型,只是我們在計算的時候做了一些轉化,從而避免了使用log進行計算,加速了計算的過程。兩者的內在邏輯是一樣的。那怎麼實現的加速計算呢?這裏用到了高等數學當中的泰勒展開,我們將log運算通過泰勒公式展開,轉化成多項式的計算,從而加速信息熵的計算。

我們來做一個簡單的推導:

\[\begin{aligned} \ln(x) \approx \ln(x_0) + (x-x_0)\ln'(x_0) + o(x) \end{aligned} \]

我們把\(x_0 =1\)代入,可以得到:\(\ln(x)=x – 1 + o(x)\),其中o(x)是關於x的高階無窮小。我們把這個式子套入信息熵的公式當中:

\[\begin{aligned} H(x) &= -\sum_{i=1}^k p_i\ln p_i \\ &\approx \sum_{i=1}^k p_i(1-p_i) \end{aligned} \]

這個就是Gini指數的計算公式,這裏的pi表示類別i的概率,其實就是類別i的樣本佔全體樣本的比例。那麼上面的式子也可以看成是從數據集當中抽取兩條樣本,它們類別不一致的概率。

因此Gini指數越小,說明數據集越集中,也就是純度越高。它的概念等價於信息熵,熵越小說明信息越集中,兩者的概念是非常近似的。所以當我們使用Gini指數來作為劃分依據的時候,選擇的是切分之後Gini指數盡量小的切分方法,而不是盡量大的。

從上面的公式當中,我們可以發現相比於信息熵的log運算,Gini指數只需要簡單地計算比例和基礎運算就可以得到結果了,顯然運算速度要快得多。並且由於是通過泰勒展開逼近的,整體的性能也並不差,我們可以看下下面這張經典的圖感受一下:

從上圖當中可以看出來,Gini指數和信息熵的效果非常接近,一樣可以非常好地反應數據劃分的純度。

拆分與剪枝

剛才我們介紹CART算法特性的時候提到過,CART算法每次拆分數據都是二分的,這點和C4.5處理連續性特徵的邏輯很像。但有兩點不同,第一點是CART對於離散型和連續性特徵都如此操作,另外一點是,CART算法當中一個特徵可以重複使用。

舉個例子,在之前的算法當中,比如說西瓜的直徑是一個特徵。那麼當我們判斷過西瓜的直徑小於10cm之後,西瓜的直徑這個特徵就會從數據當中移除,之後再也不會用到。但是在CART算法當中不是如此,比如當我們先後根據西瓜的直徑以及西瓜是否有藤這兩個特徵對數據進行拆分之後,對於ID3和C4.5算法來說,西瓜的直徑這個特徵已經不可以再用來作為劃分的依據了,但是CART算法當中可以,我們仍然可以繼續使用之前已經用過的特徵。

我們用一張圖來展示,大概是下面這個樣子:

我們觀察一下最左側的子樹,直徑這個特徵出現了不止一次,這其實是很合理的。然而這也會有一個問題,就是由於沒有了特徵只能用一次這個限制,這樣會導致這棵樹無限膨脹,尤其是在連續性特徵很多的情況下,很容易陷入過擬合。為了放置過擬合,增加模型的泛化能力,我們需要對生成的這棵樹進行剪枝。

剪枝的方案主流的有兩種,一種是預剪枝,一種是后剪枝。所謂的預剪枝,即是在生成樹的時候就對樹的生長進行限制,防止過度擬合。而後剪枝則是在樹已經生成之後,對過擬合的部分進行修剪。其中預剪枝比較容易理解,比如我們可以限制決策樹在訓練的時候每個節點的數據只有在達到一定數量的情況下才會進行分裂,否則就成為恭弘=叶 恭弘子節點保留。或者我們可以限制數據的比例,當節點中某個類別的佔比超過閾值的時候,也可以停止生長。

后剪枝相對來說複雜一些,需要我們在生成樹之後通過一些機制尋找可以剪枝的部分,對整棵樹進行修剪。比如在CART算法當中常用的剪枝策略是CCP,它的英文全寫是Cost-Complexity Pruning,即代價複雜度剪枝。這個策略設計了一個指標來衡量一棵子樹的複雜度代價,我們可以對這個代價設置閾值來進行剪枝。

這個策略的精髓在於下面這個式子:

\[c = \frac{R(t) – R(T_t)}{|N_t| – 1} \]

這個式子當中的c就是指的剪枝帶來的代價,t代表剪枝之後的子樹,\(T_t\)表示剪枝之前的子樹。R(t)表示剪枝之後的誤差代價\(R(T_t)\)表示剪枝之前的誤差代價。其中誤差代價的定義是:\(R(t) = r(t) * p(t)\),r(t)是節點t的誤差率,p(t)是t上數據占所有數據的比例。

我們來看個例子:

假設我們知道所有數據一共有100條,那麼我們代入公式算一下,可以得到\(R(t) = r(t) * p(t) = \frac{11}{23} * \frac{23}{100} = \frac{11}{100}\)

子樹的誤差代價是:

\[R(T_t) = \sum R(i)=(\frac{2}{6}*\frac{6}{100})+ (\frac{0}{3}*\frac{3}{100}) + (\frac{2}{8}*\frac{8}{100})=\frac{4}{100} \]

所以可以得到\(c=\frac{11/100 – 4/100}{3 – 1}=\frac{7}{200}\)

c越大說明剪枝帶來的偏差越大,也就是說越不能剪,相反c很小說明偏差不大,可以減掉。我們只需要設置閾值,然後計算每一棵子樹的c來判斷是否能夠剪枝即可。

代碼實現

我們之前已經實現過了C4.5算法,再來實現CART可以說是非常簡單了,因為它相比於C4.5還少了離散類型這種情況,可以全部當做是連續型類型來處理。

我們只需要把之前的信息增益比改成Gini指數即可:

from collections import Counter

def gini_index(dataset):
    dataset = np.array(dataset)
    n = dataset.shape[0]
    if n == 0:
        return 0
    # sigma p(1-p) = 1 - sigma p^2
    counter = Counter(dataset[:, -1])
    ret = 1.0
    for k, v in counter.items():
        ret -= (v / n) ** 2
    return ret

def split_gini(dataset, idx, threshold):
    left, right = [], []
    n = dataset.shape[0]
    # 根據閾值拆分,拆分之後計算新的Gini指數
    for data in dataset:
        if data[idx] < threshold:
            left.append(data)
        else:
            right.append(data)
    left, right = np.array(left), np.array(right)
   	# 拆分成兩半之後,乘上所佔的比例
    return left.shape[0] / n * gini_index(left) + right.shape[0] / n * gini_index(right)

然後選擇拆分的函數稍微調整一下,因為Gini指數越小越好,之前的信息增益和信息增益比都是越大越好。代碼的框架基本上也沒有變動,只是做了一些微調:

def choose_feature_to_split(dataset):
    n = len(dataset[0])-1
    m = len(dataset)
    # 記錄最佳Gini,特徵和閾值
    bestGini = 1.0
    feature = -1
    thred = None
    for i in range(n):
        threds = get_thresholds(dataset, i)
        for t in threds:
            # 遍歷所有的閾值,計算每個閾值的信息增益比
            ratio = split_gini(dataset, i, t)
            if ratio < bestGini:
                bestGini, feature, thred = ratio, i, t
    return feature, thred

建樹和預測的部分都和之前C4.5算法基本一致,只需要去掉離散類型的判斷即可,大家可以參考一下之前文章當中的代碼。

總結

到這裏,我們關於決策樹模型的內容就算是結束了,我們從基本的決策樹原理,再到ID3、C4.5以及CART算法,都已經囊括了。這些知識儲備足以應對面試當中關於決策樹模型的問題了

雖然在實際的生產過程當中,我們已經用不到決策樹了,還不是基本用不到,幾乎是完全用不到。但是它的思想非常重要,是後續很多模型的基礎,比如隨機森林、GBDT等模型,都是在決策樹的基礎上建立起來的。所以我們深入理解決策樹的原理對於我們後續的進階學習非常重要。

最後, 我把完整的代碼發在了paste.ubuntu上,需要的同學可以在公眾號後台回復“決策樹”獲取。

如果喜歡本文,可以的話,請點個關注,給我一點鼓勵,也方便獲取更多文章。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

網頁設計最專業,超強功能平台可客製化

單獨囚禁在水池2年 日本311倖存海豚抑鬱離世

摘錄自2020年4月15日鏡週刊報導

國際動保組織「海豚計畫」(Dolphin project)報導指出,日本寬吻海豚「Honey」於2005年在日本太地町被捕獲,自此生活在千葉線犬吠埼海洋公園僅80平方公尺大的水池中,與另一隻海豚、46隻企鵝及數百種魚類一起生活。

311大地震後面臨觀光衰退和建築物老舊,2008年11月犬吠埼海洋公園被爆出營運困難負債,正尋找買家,去年初終於轉賣,但如今整個園區卻呈現廢棄狀態,也沒有遊客造訪,僅安排員工前來餵食。另一隻海豚於2017年死亡,「Honey」自此單獨每天在這廢棄的水池中游來游去,對習性群居的海豚而言,這無疑是極大的折磨。

動保組織「海豚計畫」曾試圖聯繫買下海豚「Honey」,盼為牠找到合適的居所安享晚年,但為時已晚,3月初「Honey」狀況已經不太好,3月29日牠因阻塞性腸炎,死在待了泰半生的水池。

國際新聞
日本
核災
展示動物
動物福利

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

※別再煩惱如何寫文案,掌握八大原則!

殼牌石油拚減碳 誓言最遲2050年達零排放

摘錄自2020年4月16日聯合報報導

國際石油天然氣巨擘荷蘭皇家殼牌集團(Royal Dutch Shell)今(16日)誓言,在2050年前要達成「碳中和」(Carbon Neutral)目標,和競爭對手英國石油公司(BP)的承諾一樣。

法新社報導,殼牌執行長范柏登(Ben vanBeurden)在聲明中表示,社會對於氣候變遷的期許瞬息萬變,殼牌需要再進一步自我要求,計畫最晚在2050年成為零排放的能源企業。殼牌將在2050年前把自家能源產品的「淨碳足跡」減少約65%;在2030年減少30%。

溫室氣體
能源議題
全球變遷
氣候變遷
能源轉型
國際新聞
殼牌
減碳宣言
零排放
石油

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

德動物園面臨斷炊 列安樂死名單

摘錄自2020年4月16日醒報報導

自德國於3月15日下達封城令後,遊客銳減,新明斯特動物園財務吃緊,為了解決動物捱餓的問題,園方已列出緊急應變方案,考慮將部分動物安樂死,並宰殺作為其他動物的食物。

柏林動物園協會(VdZ)強調,動物園在休館期間無法大幅削減開支,每日仍須支出一定人力與金錢成本餵食並照顧動物,維持宜居的環境及溫度條件,一旦失去門票收入,便面臨龐大財務壓力。德國政府已推出高達7500億歐元的紓困方案,VdZ也已籲請總理梅克爾撥款1億歐元,作為動物園產業的緊急支應金。

國際新聞
德國
動物園
展示動物
動物福利

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

日本大鯢數量急減 雜交問題嚴重 水族館推大鯢布偶提升國民關注

文:宋瑞文

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

※回頭車貨運收費標準

太空可見!威尼斯疫情前後巨大變化 衛星對比照曝光

摘錄自2020年4月17日自由時報報導

武漢肺炎疫情持續蔓延,各國經濟無不受到影響,但人類社會活動暫停對地球的正面影響也已明顯出現,歐洲太空總署近日公布義大利水都威尼斯的衛星空拍對比照,只見去年同期與今年同期相比,當地水質狀況截然不同。

根據《CNN》報導,歐洲太空總署(European Space Agency)近日公布由Sentinel-2衛星拍攝的威尼斯空拍照,只見當地去年4月19日時水質十分混濁,鄰近水域幾乎都是黃澄澄一片泥沙,並有大量船隻在運行;作為對比,今年4月13日該水域已清澈見底。

威尼斯衛星空拍對比照。照片來源:
歐洲太空總署( CC BY-SA 3.0 IGO)


土地水文
土地利用
生物多樣性
國際新聞
義大利
威尼斯
水質
動物與大環境變遷
武漢肺炎
水文

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

※回頭車貨運收費標準

加州紅潮「藍影浮動」 夜光藻美麗的背後隱藏殺機

摘錄自2020年04月19日ETtoday新聞雲美國報導

佛羅里達西南部海域自2017年10月開始出現紅潮,微小藻類引起這種有害的藻華現象(algal booms),不同的藻類造成不同顏色。根據《CNN》報導,這位遊客在加州的紐波特海灘(Newport Beach)目睹了紅潮,海水中的「夜光藻」讓海水呈現「藍色螢光」。如果海岸一片平靜倒看不出異常,但隨著潮水拍岸,海中的藻華也隨之翻湧,浮現魅惑的亮藍色,在黑夜中宛如海中銀河。

紅潮讓許多遊客趨之若鶩,離島馬祖也有如此美景可欣賞。然而美麗的背後卻伴隨著死亡,根據《國家地理頻道》報導,佛羅里達南部的海灘被成千海洋生物的屍體覆蓋,各種魚類、螃蟹、海牛、海豚、海龜等生物,因為吃下大量海藻而中毒。

而研究指出,人為排放的養分是造成藻華數目急遽上升的原因,而大型風暴通過的地區也可能出現紅潮異常的情況。然而目前對於紅潮是「人為」還是「天然」造成仍存在爭議。

全球變遷
氣候變遷
國際新聞
加州
紅潮
藻華現象

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

※教你寫出一流的銷售文案?

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

鋁複合材料能存氣體 氫氣車電池新招

摘錄自2020年4月19日聯合新聞網報導

美國西北大學法爾哈教授所帶領的團隊,最近成功研發一種以鋁做為主元素的複合材料:NU-1501,有望成為氫氣車大量儲存氣體的新選項。該材料在結構上與海綿相似,擁有許多小孔可儲存氣體,NU-1501可透過壓力的不同來儲存或釋放氣體。比起現有的氣體儲存槽更加安全、輕量與便宜,若加以應用,有極大潛力。

為了降低交通運輸業所造成的碳排放,可達到零碳排的氫氣車近年來成為重要的研究主軸。氫氣車主要透過氫和氧的化學反應來產生電,過程並不會產生任何二氧化碳。但因為氫氣十分易燃且體積龐大,在未加壓的狀況下,跑100公里需要11,000公升的氫氣。

目前業界主要採取將氫氣加壓到700巴,比汽車胎壓還要高出300倍,除了有安全疑慮外,特別設計過的氣體儲存槽也相當笨重與昂貴。而NU-1051除了能攜帶更多的氫氣外,也只需要比較低的壓力,因此十分具有發展潛力。

能源議題
環境經濟
能源轉型
循環經濟
國際新聞
氫氣車
海綿

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※回頭車貨運收費標準

台中搬家公司費用怎麼算?