都市における温度データを考える。
measure = [ {'city': 'Dubai', 'temperature': 33.}, {'city': 'London', 'temperature': 12.}, {'city': 'San Fransisco', 'temperature': 18.} ]
機会学習をする際にカテゴリデータの形式を”処理”しやすい形式に変換することはよく見られる。この際に考えられる方法は何があるか。
- 頭文字
- いくつかの文字を利用したコード
- 数字とのマッピング
まず1)については都市の数が増えたときに重なる可能性がある。次に2)についてはコードを自分で管理するために面倒くさい。
そうなると3)の数字とのマッピングがある。
measure_x = [ {'city': 10, 'temperature': 33.}, {'city': 12, 'temperature': 12.}, {'city': 20, 'temperature': 18.} ]
ここに落とし穴がある。数字にすると、重なることもないし、都市の数が増えたら、数字を増やしていけばよい。しかし多くの学習器は数字の場合には、順序と計算ができることが前提になる。
例えば順序という意味では、Dubai < London < San Franciscoである。また計算ができるとは例えばDubai – Londonといった計算ができるということだ。
このようなカテゴリデータについて特徴抽出をするためにはDictVectorizeが利用できる。
sklearn.feature_extraction.DictVectorizer — scikit-learn 0.21.3 …
class sklearn.feature_extraction.DictVectorizer(dtype=<class ‘numpy.float64’>, separator=’=’, sparse=True, sort=True)
使い方はいたって簡単である。dtypeにカテゴリデータのフォーマットを指定する。またカテゴリ値が極端に大きい場合もしくはパフォーマンスが悪い場合を除けば、sparse=Falseを指定するほうが取り扱いやすい。
from sklearn.feature_extraction import DictVectorizer vec = DictVectorizer(sparse=False, dtype=int) vec.fit_transform(measure) # array([[ 1, 0, 0, 33], [ 0, 1, 0, 12], [ 0, 0, 1, 18]], dtype=int32)
少々わかりにくいが1~3列目がcityを表している。確認するためにはget_feature_names()を利用すればよい。
print(vec.get_feature_names()) # ['city=Dubai', 'city=London', 'city=San Fransisco', 'temperature']
カテゴリデータが増えた場合にはsparse=Trueとする。これによりスパース行列が作成される。
from sklearn.feature_extraction import DictVectorizer vec = DictVectorizer(sparse=True, dtype=int) X = vec.fit_transform(measure) # <3x4 sparse matrix of type '<class 'numpy.int32'>' with 6 stored elements in Compressed Sparse Row format> print(X) # (0, 0) 1 (0, 3) 33 (1, 1) 1 (1, 3) 12 (2, 2) 1 (2, 3) 18
行列の内容を確認するには、toarray()で変換する。
X.toarray() # array([[ 1, 0, 0, 33], [ 0, 1, 0, 12], [ 0, 0, 1, 18]], dtype=int32)