XGBoost之類別特徵的處理

目錄

Label encoding與 One-Hot encoding

Label encoding

one-hot encoding

利用神經網絡的Embedding層處理類別特徵

Embedding簡介

Network Embedding算法分類

Embedding實戰


轉載:https://www.biaodianfu.com/categorical-features.html

XGBoost之類別特徵的處理

無論是XGBoost還是其他的Boosting Tree,使用的Tree都是cart迴歸樹,這也就意味着該類提升樹算法只接受數值特徵輸入,不直接支持類別特徵,默認情況下,xgboost會把類別型的特徵當成數值型。事實上,對於類別特徵的處理,參考XGBoost PPT如下:

 

xgboost 樹模型其實是不建議使用one-hot編碼,在xgboost上面的 issue 也提到過,相關的說明如下

I do not know what you mean by vector. xgboost treat every input feature as numerical, with support for missing values and sparsity. The decision is at the user

So if you want ordered variables, you can transform the variables into numerical levels(say age). Or if you prefer treat it as categorical variable, do one hot encoding.

在另一個issues上也提到過(tqchen commented on 8 May 2015):

One-hot encoding could be helpful when the number of categories are small( in level of 10 to 100). In such case one-hot encoding can discover interesting interactions like (gender=male) AND (job = teacher).

While ordering them makes it harder to be discovered(need two split on job). However, indeed there is not a unified way handling categorical features in trees, and usually what tree was really good at was ordered continuous features anyway..

總結起來的結論,大至兩條:

  • 對於類別有序的類別型變量,比如 age 等,當成數值型變量處理可以的。對於非類別有序的類別型變量,推薦 one-hot。但是 one-hot 會增加內存開銷以及訓練時間開銷。
  • 類別型變量在範圍較小時(tqchen 給出的是[10,100]範圍內)推薦使用

Label encoding與 One-Hot encoding

xgboost是不支持category特徵的,在訓練模型之前,需要我們進行預處理,可以根據特徵的具體形式來選擇:

  • 無序特徵:one-hot encoding,比如城市
  • 有序特徵:label encoding,比如版本號

Label encoding

Label encoding是使用字典的方式,將每個類別標籤與不斷增加的整數相關聯,即生成一個名爲class_的實例數組的索引。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

from sklearn.preprocessing import LabelEncoder

 

le = LabelEncoder()

 

city_list = ["paris", "paris", "tokyo", "amsterdam"]

 

le.fit(city_list)

print(le.classes_)  # 輸出爲:['amsterdam' 'paris' 'tokyo']

 

city_list_le = le.transform(city_list)  # 進行Encode

print(city_list_le)  # 輸出爲:[1 1 2 0]

 

city_list_new = le.inverse_transform(city_list_le)  # 進行decode

print(city_list_new) # 輸出爲:['paris' 'paris' 'tokyo' 'amsterdam']

如果是多列數據如何進行方便的編碼。

方案一:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

from sklearn.preprocessing import LabelEncoder

from collections import defaultdict

import pandas as pd

 

d = defaultdict(LabelEncoder)

 

df = pd.DataFrame({

    'pets': ['cat', 'dog', 'cat', 'monkey', 'dog', 'dog'],

    'owner': ['Champ', 'Ron', 'Brick', 'Champ', 'Veronica', 'Ron'],

    'location': ['San_Diego', 'New_York', 'New_York', 'San_Diego', 'San_Diego',

                 'New_York']

})

 

 

# Encoding the variable

fit = df.apply(lambda x: d[x.name].fit_transform(x))

 

# Inverse the encoded

fit.apply(lambda x: d[x.name].inverse_transform(x))

 

# Using the dictionary to label future data

df.apply(lambda x: d[x.name].transform(x))

方案2:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

import pandas as pd

from sklearn.preprocessing import LabelEncoder

from sklearn.pipeline import Pipeline

 

# Create some toy data in a Pandas dataframe

fruit_data = pd.DataFrame({

    'fruit':  ['apple','orange','pear','orange'],

    'color':  ['red','orange','green','green'],

    'weight': [5,6,3,4]

})

 

class MultiColumnLabelEncoder:

    def __init__(self,columns = None):

        self.columns = columns # array of column names to encode

 

    def fit(self,X,y=None):

        return self # not relevant here

 

    def transform(self,X):

        '''

        Transforms columns of X specified in self.columns using

        LabelEncoder(). If no columns specified, transforms all

        columns in X.

        '''

        output = X.copy()

        if self.columns is not None:

            for col in self.columns:

                output[col] = LabelEncoder().fit_transform(output[col])

        else:

            for colname,col in output.iteritems():

                output[colname] = LabelEncoder().fit_transform(col)

        return output

 

    def fit_transform(self,X,y=None):

        return self.fit(X,y).transform(X)

參考鏈接:https://stackoverflow.com/questions/24458645/label-encoding-across-multiple-columns-in-scikit-learn

方案三:pd.factorize()

pandas的factorize()可以將Series中的標稱型數據映射稱爲一組數字,相同的標稱型映射爲相同的數字。factorize函數的返回值是一個tuple(元組),元組中包含兩個元素。第一個元素是一個array,其中的元素是標稱型元素映射爲的數字;第二個元素是Index類型,其中的元素是所有標稱型元素,沒有重複。

Pandas factorize()和sklearn Label encoding的主要不同是sklearn編碼器通過fit和transform方法用於sklearn piplines

LabelBinarizer

這種方法很簡單,在許多情況下效果很好,但他有一個缺點:所有的標籤都變成了數字,然後算法模型直接將根據其距離來考慮相似的數字,而不考慮標籤的具體含義。因此,通常優選獨熱編碼(one-hot encoding)將數據二進制化。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

from sklearn.preprocessing import LabelBinarizer

 

lb = LabelBinarizer()

 

city_list = ["paris", "paris", "tokyo", "amsterdam"]

 

lb.fit(city_list)

print(lb.classes_)  # 輸出爲:['amsterdam' 'paris' 'tokyo']

 

city_list_le = lb.transform(city_list)  # 進行Encode

print(city_list_le)  # 輸出爲:

# [[0 1 0]

#  [0 1 0]

#  [0 0 1]

#  [1 0 0]]

 

city_list_new = lb.inverse_transform(city_list_le)  # 進行decode

print(city_list_new)  # 輸出爲:['paris' 'paris' 'tokyo' 'amsterdam']

DictVectorizer

當類別的特徵被構造成類似於字典的列表時,列表中的值僅僅需要時幾個特徵的值而不需要很密集,此時可採用另一種分類方法。DictVectorizer可以用於將各列使用標準的Python dict對象表示的特徵數組,轉換成sklearn中的estimators可用的NumPy/SciPy表示的對象。Python的dict的優點是,很方便使用,稀疏,可以存儲feature名和值。DictVectorizer實現了一個稱爲one-of-K或者”one-hot”編碼的類別特徵。類別特徵是“屬性-值”對,它的值嚴格對應於一列無序的離散概率(比如:topic id, 對象類型,tags, names…)

下例中,”city”是類別的屬性,而”temperature”是一個傳統的數值型feature:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

from sklearn.feature_extraction import DictVectorizer

 

measurements = [

    {'city': 'Dubai', 'temperature': 33.},

    {'city': 'London', 'temperature': 12.},

    {'city': 'San Fransisco', 'temperature': 18.},

]

 

vec = DictVectorizer()

measurements_vec = vec.fit_transform(measurements)

print(measurements_vec)

  # 輸出內容:

  # (0, 0) 1.0

  # (0, 3) 33.0

  # (1, 1) 1.0

  # (1, 3) 12.0

  # (2, 2) 1.0

  # (2, 3) 18.0

print(measurements_vec.toarray())

# 輸出內容

# [[ 1.  0.  0. 33.]

#  [ 0.  1.  0. 12.]

#  [ 0.  0.  1. 18.]]

 

feature_names = vec.get_feature_names()

print(feature_names)  # 輸出:['city=Dubai', 'city=London', 'city=San Fransisco', 'temperature']

FeatureHasher

一般的vectorizer是爲訓練過程中遇到的特徵構建一個hash table,而FeatureHasher類則直接對特徵應用一個hash函數來決定特徵在樣本矩陣中的列索引。這樣的做法使得計算速度提升並且節省了內存,the hasher無法記住輸入特徵的樣子,而且不遜在你想變換操作:inverse_transform。

因爲哈希函數可能會導致本來不相關的特徵之間發生衝突,所以使用了有符號的hash函數。對一個特徵,其hash值的符號決定了被存儲到輸出矩陣中的值的符號。通過這種方式就能夠消除特徵hash映射時發生的衝突而不是累計衝突。而且任意輸出的值的期望均值是0。sklearn中的FeatureHasher使用了MurmurHash 3作爲其Hash算法。

FeatureHasher的輸出通常是CSR格式的scipy.sparse matrix。Feature hashing 可被用於文檔分類中去,但是與text.CountVectorizer不同,FeatureHasher不做單詞切分或其他的預處理操作,除了Unicode-to-UTF-8編碼以外。

one-hot encoding

什麼是one-hot encoding

在實際的機器學習的應用任務中,特徵有時候並不總是連續值,有可能是一些分類值,如性別可分爲“male”和“female”。在機器學習任務中,對於這樣的特徵,通常我們需要對其進行特徵數字化,比如有如下三個特徵屬性:

  • 性別:[“male”,”female”]
  • 地區:[“Europe”,”US”,”Asia”]
  • 瀏覽器:[“Firefox”,”Chrome”,”Safari”,”Internet Explorer”]

對於某一個樣本,如[“male”,”US”,”Internet Explorer”],我們需要將這個分類值的特徵數字化,最直接的方法,我們可以採用序列化的方式:[0,1,3]。但是,即使轉化爲數字表示後,上述數據也不能直接用在我們的分類器中。因爲,分類器往往默認數據是連續的,並且是有序的。按照上述的表示,數字並不是有序的,而是隨機分配的。這樣的特徵處理並不能直接放入機器學習算法中。

爲了解決上述問題,其中一種可能的解決方法是採用獨熱編碼(One-Hot Encoding)。獨熱編碼,又稱爲一位有效編碼。其方法是使用N位狀態寄存器來對N個狀態進行編碼,每個狀態都由他獨立的寄存器位,並且在任意時候,其中只有一位有效。可以這樣理解,對於每一個特徵,如果它有m個可能值,那麼經過獨熱編碼後,就變成了m個二元特徵。並且,這些特徵互斥,每次只有一個激活。因此,數據會變成稀疏的。

對於上述的問題,性別的屬性是二維的,同理,地區是三維的,瀏覽器則是四維的,這樣,我們可以採用One-Hot編碼的方式對上述的樣本“[“male”,”US”,”Internet Explorer”]”編碼,“male”則對應着[1,0],同理“US”對應着[0,1,0],“Internet Explorer”對應着[0,0,0,1]。則完整的特徵數字化的結果爲:[1,0,0,1,0,0,0,0,1]。

爲什麼能使用One-Hot Encoding?

  • 使用one-hot編碼,將離散特徵的取值擴展到了歐式空間,離散特徵的某個取值就對應歐式空間的某個點。在迴歸,分類,聚類等機器學習算法中,特徵之間距離的計算或相似度的計算是非常重要的,而我們常用的距離或相似度的計算都是在歐式空間的相似度計算,計算餘弦相似性,也是基於的歐式空間。
  • 將離散型特徵使用one-hot編碼,可以會讓特徵之間的距離計算更加合理。比如,有一個離散型特徵,代表工作類型,該離散型特徵,共有三個取值,不使用one-hot編碼,計算出來的特徵的距離是不合理。那如果使用one-hot編碼,顯得更合理。

獨熱編碼優缺點

  • 優點:獨熱編碼解決了分類器不好處理屬性數據的問題,在一定程度上也起到了擴充特徵的作用。它的值只有0和1,不同的類型存儲在垂直的空間。
  • 缺點:當類別的數量很多時,特徵空間會變得非常大。在這種情況下,一般可以用PCA(主成分分析)來減少維度。而且One-Hot Encoding+PCA這種組合在實際中也非常有用。

One-Hot Encoding的使用場景

  • 獨熱編碼用來解決類別型數據的離散值問題。將離散型特徵進行one-hot編碼的作用,是爲了讓距離計算更合理,但如果特徵是離散的,並且不用one-hot編碼就可以很合理的計算出距離,那麼就沒必要進行one-hot編碼,比如,該離散特徵共有1000個取值,我們分成兩組,分別是400和600,兩個小組之間的距離有合適的定義,組內的距離也有合適的定義,那就沒必要用one-hot 編碼。
  • 基於樹的方法是不需要進行特徵的歸一化,例如隨機森林,bagging 和 boosting等。對於決策樹來說,one-hot的本質是增加樹的深度,決策樹是沒有特徵大小的概念的,只有特徵處於他分佈的哪一部分的概念。

One-Hot使用示例

1、基於sklearn 的one hot encoding:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

import pandas as pd

from sklearn.preprocessing import LabelEncoder

from sklearn.preprocessing import OneHotEncoder

 

df = pd.DataFrame([

    ['green', 'Chevrolet', 2017],

    ['blue', 'BMW', 2015],

    ['yellow', 'Lexus', 2018],

])

df.columns = ['color', 'make', 'year']

 

le_color = LabelEncoder()

le_make = LabelEncoder()

df['color_encoded'] = le_color.fit_transform(df.color)

df['make_encoded'] = le_make.fit_transform(df.make)

 

color_ohe = OneHotEncoder()

make_ohe = OneHotEncoder()

X = color_ohe.fit_transform(df.color_encoded.values.reshape(-1, 1)).toarray()

Xm = make_ohe.fit_transform(df.make_encoded.values.reshape(-1, 1)).toarray()

 

dfOneHot = pd.DataFrame(X, columns=["Color_" + str(int(i)) for i in range(X.shape[1])])

df = pd.concat([df, dfOneHot], axis=1)

 

dfOneHot = pd.DataFrame(Xm, columns=["Make" + str(int(i)) for i in range(X.shape[1])])

df = pd.concat([df, dfOneHot], axis=1)

參考鏈接:http://www.insightsbot.com/blog/McTKK/python-one-hot-encoding-with-scikit-learn

2、基於pandas的one hot encoding:

其實如果我們跳出 scikit-learn, 在 pandas 中可以很好地解決這個問題,用 pandas 自帶的get_dummies函數即可

1

2

3

4

5

6

7

8

9

10

11

12

import pandas as pd

 

df = pd.DataFrame([

    ['green', 'Chevrolet', 2017],

    ['blue', 'BMW', 2015],

    ['yellow', 'Lexus', 2018],

])

df.columns = ['color', 'make', 'year']

 

 

df_processed = pd.get_dummies(df, prefix_sep="_", columns=df.columns[:-1])

print(df_processed)

get_dummies的優勢在於:

  • 本身就是 pandas 的模塊,所以對 DataFrame 類型兼容很好
  • 不管你列是數值型還是字符串型,都可以進行二值化編碼
  • 能夠根據指令,自動生成二值化編碼後的變量名

get_dummies雖然有這麼多優點,但畢竟不是 sklearn 裏的transformer類型,所以得到的結果得手動輸入到 sklearn 裏的相應模塊,也無法像 sklearn 的transformer一樣可以輸入到pipeline中進行流程化地機器學習過程。

參考鏈接:https://blog.cambridgespark.com/robust-one-hot-encoding-in-python-3e29bfcec77e

利用神經網絡的Embedding層處理類別特徵

Embedding簡介

Embedding的起源和火爆都是在NLP中的,經典的word2vec都是在做word embedding這件事情,而真正首先在結構數據探索embedding的是在kaggle上的《Rossmann Store Sales》中的rank 3的解決方案,作者在比賽完後爲此方法整理一篇論文放在了arXiv,文章名:《Entity Embeddings of Categorical Variables》。

Embedding也被稱爲嵌套,是將大型稀疏矢量映射到一個保留語義關係的低維空間。在此模塊的隨後幾個部分中,我們將從直觀角度、概念角度和編程角度來詳細探討嵌套。

要解決稀疏輸入數據的核心問題,您可以將高維度數據映射到低維度空間。即便是小型多維空間,也能自由地將語義上相似的項歸到一起,並將相異項分開。矢量空間中的位置(距離和方向)可對良好的嵌套中的語義進行編碼。例如,下面的真實嵌套可視化圖所展示的幾何關係圖捕獲了國家與其首都之間的語義關係。

 

嵌套充當查詢表

嵌套是一個矩陣,每列表示您詞彙中的一項所對應的矢量。要獲得某個詞彙項的密集矢量,您可以檢索該項所對應的列。但是,如何轉換字詞矢量的稀疏包呢?要獲得表示多個詞彙項(例如,一句或一段中的所有字詞)的稀疏矢量的密集矢量,您可以檢索各項的嵌套,然後將它們相加。如果稀疏矢量包含詞彙項的計數,則您可以將每項嵌套與其對應項的計數相乘,然後再求和。這些運算可能看起來很眼熟吧。

嵌套查詢充當矩陣乘法

我們剛剛闡述的查詢、乘法和加法程序等效於矩陣乘法。假設有一個 1×N的稀疏表示 S 和一個 N×M 的嵌套表 E,矩陣乘法 S×E 可以得出密集矢量 1×M。這個概念用神經網絡圖來表示如下:

 

但首要問題是,如何獲取 E 呢?我們將在下一部分介紹如何獲取嵌套。

Network Embedding,即將網絡節點、community投影到低維向量空間,用於node classification、link prediction、community detection、visualization等任務。

核心假設:節點間距離越近,embedding向量越接近,定義LOSS爲:

 

Network Embedding算法分類

基於矩陣特徵向量計算(譜聚類)

目標是將相似性高的兩個節點,映射到低維空間後依然保持距離相近,其損失函數定義爲:

 

基於random walk框架計算(Deep Walk & Node2Vec)

 

基於Deep Learning框架計算 SDNE(Structural Deep Network Embeddings)

主要思想:將節點的相似性向量 Si直接作爲模型的輸入,通過 Auto-encoder 對這個向量進行降維壓縮,得到其向量化後的結果 $Z_i#。其損失函數定義爲:

 

模型框架爲:

GCN(Graph Convolutional Networks)

主要思想:將節點本身及其鄰居節點的屬性(比如文本信息)或特徵(比如統計信息)編碼進向量中,引入了更多特徵信息,並且在鄰居節點間共享了一些特徵或參數,基於最終的目標(如節點分類)做整體優化。

模型框架示意和計算流程:

更多參考:

Embedding實戰

使用Keras進行Embedding

Keras對Tensorflow又進行了一層封裝,操作簡單,功能強大。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

# 構造輸入數據

# 輸入數據是320*6,320個樣本,6個類別特徵,且類別特徵的可能值是0到36之間(37個)。

# 對這6個特徵做one-hot的話,應該爲37*6,

# embedding就是使1個特徵原本應該one-hot的37維變爲3維(手動設定,也可以是其它),因爲有36個類別特徵

# 這樣輸出的結果就應該是3*6

# 參考鏈接:https://keras.io/zh/layers/embeddings/

# 建議降維的維度爲 math.ceil(category_count ** 0.25)

 

import numpy as np

np.random.seed(42)

input_array = np.random.randint(37, size=(320, 6))

print(input_array)

 

 

import tensorflow as tf

from keras import backend as K

from keras.models import Sequential

from keras.layers.embeddings import Embedding

 

 

with tf.Session() as sess:

    K.set_session(sess)

    model = Sequential()

    model.add(Embedding(37, 3, input_length=6))

    model.compile('rmsprop', 'mse')

    output_array = model.predict(input_array)

    print(output_array)

    # weight = model.get_weights()

    # print(weight)

在上述的代碼中,我們可以看到6個類別特徵的值都在0到37,並且我們沒有對模型進行訓練,而是直接就搭建了一個網絡,就輸出結果了。在真實的應用中,不是這樣。有2點需要改進:

  • 對每一個類別特徵構建一個embedding層。對embedding層進行拼接。
  • 訓練網絡,得到訓練後的embedding層的輸出作爲類別特徵one-hot的替換,這樣的embedding的輸出更精確

爲了解決上述的2個問題,我們這裏還是人工構建訓練集,我們搭建的模型如圖:

 

從模型中,我們可以看到,這是符合現實世界的數據集的:即既有分類特徵,又有連續特徵。我們先訓練一個網絡,embedding_3和embedding_4層的輸出結果就是用embedding處理類別特徵後的結果。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

import numpy as np

import tensorflow as tf

from keras.models import Model

from keras.layers import Input, Dense, Concatenate, Reshape, Dropout

from keras.layers.embeddings import Embedding

from keras import backend as K

from keras.utils import plot_model

 

session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)

sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)

K.set_session(sess)

 

 

def build_embedding_network():

    """

    以網絡結構embeddding層在前,dense層在後。即訓練集的X必須以分類特徵在前,連續特徵在後。

    """

    inputs = []

    embeddings = []

 

    input_cate_feature_1 = Input(shape=(1,))

    embedding = Embedding(10, 3, input_length=1)(input_cate_feature_1)

    embedding = Reshape(target_shape=(3,))(embedding)  # embedding後是10*1*3,爲了後續計算方便,因此使用Reshape轉爲10*3

    inputs.append(input_cate_feature_1)

    embeddings.append(embedding)

 

    input_cate_feature_2 = Input(shape=(1,))

    embedding = Embedding(4, 2, input_length=1)(input_cate_feature_2)

    embedding = Reshape(target_shape=(2,))(embedding)

    inputs.append(input_cate_feature_2)

    embeddings.append(embedding)

 

    input_numeric = Input(shape=(1,))

    embedding_numeric = Dense(16)(input_numeric)

    inputs.append(input_numeric)

    embeddings.append(embedding_numeric)

 

    x = Concatenate()(embeddings)

    x = Dense(10, activation='relu')(x)

    x = Dropout(.15)(x)

    output = Dense(1, activation='sigmoid')(x)

 

    model = Model(inputs, output)

    model.compile(loss='binary_crossentropy', optimizer='adam')

    return model

 

 

"""

構造訓練數據

輸入數據是320*3,320個樣本,2個類別特徵,1個連續特徵。

對類別特徵做entity embedding,第一個類別特徵10個,第二個類別特徵4個。對這2個特徵做one-hot的話,應該爲10+4,

對第一個類別特徵做embedding使其爲3維,對第二個類別特徵做embedding使其爲2維。3對連續特徵不做處理。這樣理想輸出的結果就應該是3+2+1。

維和2維的設定是根據實驗效果和交叉驗證設定。

"""

sample_num = 320  # 樣本數爲32

cate_feature_num = 2  # 類別特徵爲2

contious_feature_num = 1  # 連續特徵爲1

 

rng = np.random.RandomState(0)  # 保證了訓練集的復現

cate_feature_1 = rng.randint(10, size=(sample_num, 1))

cate_feature_2 = rng.randint(4, size=(sample_num, 1))

contious_feature = rng.rand(sample_num, 1)

 

X = [cate_feature_1, cate_feature_2, contious_feature]

Y = np.random.randint(2, size=(sample_num, 1))  # 二分類

 

cate_embedding_dimension = {'0': 3, '1': 2}  # 記錄類別特徵embedding後的維度。key爲類別特徵索引,value爲embedding後的維度

 

"""

訓練和預測

"""

NN = build_embedding_network()

plot_model(NN, to_file='NN.png')  # 畫出模型,需要GraphViz包。另外需要安裝 pip install pydot

 

NN.fit(X, Y, epochs=3, batch_size=4, verbose=0)

y_preds = NN.predict(X)[:, 0]

 

"""

讀embedding層的輸出結果

"""

model = NN  # 創建原始模型

for i in range(cate_feature_num):

    layer_name = NN.get_config()['layers'][cate_feature_num + i]['name']  # cate_feature_num+i就是所有embedding層

    intermediate_layer_model = Model(inputs=NN.input, outputs=model.get_layer(layer_name).output)

    intermediate_output = intermediate_layer_model.predict(X)

    intermediate_output.resize([sample_num, cate_embedding_dimension[str(i)]])

    if i == 0:

        X_embedding_trans = intermediate_output

    else:

        X_embedding_trans = np.hstack((X_embedding_trans, intermediate_output))  # 水平拼接

 

for i in range(contious_feature_num):

    if i == 0:

        X_contious = X[cate_feature_num + i]

    else:

        X_contious = np.hstack((X_contious, X[cate_feature_num + i]))

 

X_trans = np.hstack((X_embedding_trans, X_contious))  # 在類別特徵做embedding後的基礎上,拼接連續特徵,形成最終矩陣,也就是其它學習器的輸入。

 

print(X_trans[:5])  # 其中,類別特徵維度爲5(前5個),連續特徵維度爲1(最後1個)

 

weight = NN.trainable_weights[0].eval(session=sess) # embedding_1層的參數。

print(weight[:5])

參考鏈接:https://blog.csdn.net/h4565445654/article/details/78998444

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