keras中to_categorical函式解析
阿新 • • 發佈:2018-12-17
1.to_categorical的功能
簡單來說,to_categorical就是將類別向量轉換為二進位制(只有0和1)的矩陣型別表示。其表現為將原有的類別向量轉換為獨熱編碼的形式。先上程式碼看一下效果:
from keras.utils.np_utils import * #類別向量定義 b = [0,1,2,3,4,5,6,7,8] #呼叫to_categorical將b按照9個類別來進行轉換 b = to_categorical(b, 9) print(b) 執行結果如下: [[1. 0. 0. 0. 0. 0. 0. 0. 0.] [0. 1. 0. 0. 0. 0. 0. 0. 0.] [0. 0. 1. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 1. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 1. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 1. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 1. 0. 0.] [0. 0. 0. 0. 0. 0. 0. 1. 0.] [0. 0. 0. 0. 0. 0. 0. 0. 1.]]
to_categorical最為keras中提供的一個工具方法,從以上程式碼執行可以看出,將原來類別向量中的每個值都轉換為矩陣裡的一個行向量,從左到右依次是0,1,2,...8個類別。2表示為[0. 0. 1. 0. 0. 0. 0. 0. 0.],只有第3個為1,作為有效位,其餘全部為0。
2.one_hot encoding(獨熱編碼)介紹
獨熱編碼又稱為一位有效位編碼,上邊程式碼例子中其實就是將類別向量轉換為獨熱編碼的類別矩陣。也就是如下轉換:
0 1 2 3 4 5 6 7 8 0=> [1. 0. 0. 0. 0. 0. 0. 0. 0.] 1=> [0. 1. 0. 0. 0. 0. 0. 0. 0.] 2=> [0. 0. 1. 0. 0. 0. 0. 0. 0.] 3=> [0. 0. 0. 1. 0. 0. 0. 0. 0.] 4=> [0. 0. 0. 0. 1. 0. 0. 0. 0.] 5=> [0. 0. 0. 0. 0. 1. 0. 0. 0.] 6=> [0. 0. 0. 0. 0. 0. 1. 0. 0.] 7=> [0. 0. 0. 0. 0. 0. 0. 1. 0.] 8=> [0. 0. 0. 0. 0. 0. 0. 0. 1.]
那麼一道思考題來了,讓你自己編碼實現類別向量向獨熱編碼的轉換,該怎樣實現呢?
以下是我自己粗淺寫的一個小例子,僅供參考:
def convert_to_one_hot(labels, num_classes): #計算向量有多少行 num_labels = len(labels) #生成值全為0的獨熱編碼的矩陣 labels_one_hot = np.zeros((num_labels, num_classes)) #計算向量中每個類別值在最終生成的矩陣“壓扁”後的向量裡的位置 index_offset = np.arange(num_labels) * num_classes #遍歷矩陣,為每個類別的位置填充1 labels_one_hot.flat[index_offset + labels] = 1 return labels_one_hot #進行測試 b = [2, 4, 6, 8, 6, 2, 3, 7] print(convert_to_one_hot(b,9)) 測試結果: [[0. 0. 1. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 1. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 1. 0. 0.] [0. 0. 0. 0. 0. 0. 0. 0. 1.] [0. 0. 0. 0. 0. 0. 1. 0. 0.] [0. 0. 1. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 1. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0. 1. 0.]]
3.原始碼解析
to_categorical在keras的utils/np_utils.py中,原始碼如下:
def to_categorical(y, num_classes=None, dtype='float32'):
"""Converts a class vector (integers) to binary class matrix.
E.g. for use with categorical_crossentropy.
# Arguments
y: class vector to be converted into a matrix
(integers from 0 to num_classes).
num_classes: total number of classes.
dtype: The data type expected by the input, as a string
(`float32`, `float64`, `int32`...)
# Returns
A binary matrix representation of the input. The classes axis
is placed last.
# Example
```python
# Consider an array of 5 labels out of a set of 3 classes {0, 1, 2}:
> labels
array([0, 2, 1, 2, 0])
# `to_categorical` converts this into a matrix with as many
# columns as there are classes. The number of rows
# stays the same.
> to_categorical(labels)
array([[ 1., 0., 0.],
[ 0., 0., 1.],
[ 0., 1., 0.],
[ 0., 0., 1.],
[ 1., 0., 0.]], dtype=float32)
```
"""
#將輸入y向量轉換為陣列
y = np.array(y, dtype='int')
#獲取陣列的行列大小
input_shape = y.shape
if input_shape and input_shape[-1] == 1 and len(input_shape) > 1:
input_shape = tuple(input_shape[:-1])
#y變為1維陣列
y = y.ravel()
#如果使用者沒有輸入分類個數,則自行計算分類個數
if not num_classes:
num_classes = np.max(y) + 1
n = y.shape[0]
#生成全為0的n行num_classes列的值全為0的矩陣
categorical = np.zeros((n, num_classes), dtype=dtype)
#np.arange(n)得到每個行的位置值,y裡邊則是每個列的位置值
categorical[np.arange(n), y] = 1
#進行reshape矯正
output_shape = input_shape + (num_classes,)
categorical = np.reshape(categorical, output_shape)
return categorical
看過原始碼之後,確實覺得自己的程式碼還需要完善。框架裡的一些api,我們可以先自己想著來寫,然後和原始碼進行對比學習,這是一個很好的學習方法。