Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/ja/tutorials/load_data/pandas_dataframe.ipynb
25118 views
Kernel: Python 3

Licensed under the Apache License, Version 2.0 (the "License");

#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

pandas DataFrame を読み込む

このチュートリアルでは、pandas DataFrames を TensorFlow に読み込む方法の例を示します。

このチュートリアルでは、UCI Machine Learning Repository が提供する小さな心臓疾患データセットを使用します。CSV 形式で数百の行を含むデータセットです。各行は患者に関する情報で、列には属性が記述されています。この情報を使って、患者に心臓疾患があるかどうかを予測します。これは二項分類のタスクです。

pandas を使ってデータを読み取る

import pandas as pd import tensorflow as tf SHUFFLE_BUFFER = 500 BATCH_SIZE = 2

心臓疾患データセットを含む CSV ファイルをダウンロードします。

csv_file = tf.keras.utils.get_file('heart.csv', 'https://storage.googleapis.com/download.tensorflow.org/data/heart.csv')

pandas を使って CSV を読み取ります。

df = pd.read_csv(csv_file)

データは以下のように表示されます。

df.head()
df.dtypes

target 列に含まれるラベルを予測するモデルを作成します。

target = df.pop('target')

配列としての DataFrame

データのデータ型が統一されている場合、または、dtype の場合、NumPy 配列を使用できる場合であればどこでも pandas DataFrame を使用できます。これは、pandas.DataFrame クラスが __array__ プロトコルをサポートしているためであり、TensorFlow の tf.convert_to_tensor 関数がプロトコルをサポートするオブジェクトを受け入れるます。

データセットから数値特徴量を取得します (ここでは、カテゴリカル特徴量をスキップします)。

numeric_feature_names = ['age', 'thalach', 'trestbps', 'chol', 'oldpeak'] numeric_features = df[numeric_feature_names] numeric_features.head()

DataFrame は、DataFrame.values プロパティまたは numpy.array(df) を使用して NumPy 配列に変換できます。テンソルに変換するには、tf.convert_to_tensor を使用します。

tf.convert_to_tensor(numeric_features)

一般に、オブジェクトを tf.convert_to_tensor でテンソルに変換すれば、tf.Tensor を渡せる場合は、同様に渡すことができます。

Model.fit メソッド

単一のテンソルとして解釈される DataFrame は、Model.fit メソッドの引数として直接使用できます。

以下は、データセットの数値特徴に関するモデルのトレーニングの例です。

最初のステップは、入力範囲を正規化することです。そのために tf.keras.layers.Normalization レイヤーを使用します。

実行する前にレイヤーの平均と標準偏差を設定するには、必ず Normalization.adapt メソッドを呼び出してください。

normalizer = tf.keras.layers.Normalization(axis=-1) normalizer.adapt(numeric_features)

DataFrame の最初の 3 行でレイヤーを呼び出して、このレイヤーからの出力のサンプルを視覚化します。

normalizer(numeric_features.iloc[:3])

単純なモデルの最初のレイヤーとして正規化レイヤーを使用します。

def get_basic_model(): model = tf.keras.Sequential([ normalizer, tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(1) ]) model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy']) return model

DataFrame を x 引数として Model.fit に渡すと、Keras は DataFrame をNumPy 配列と同じように扱います。

model = get_basic_model() model.fit(numeric_features, target, epochs=15, batch_size=BATCH_SIZE)

tf.data を適用する

tf.data 変換を均一な dtype の DataFrame に適用する場合、Dataset.from_tensor_slices メソッドは、DataFrame の行を反復処理するデータセットを作成します。各行は、最初は値のベクトルです。モデルをトレーニングするには、(inputs, labels) のペアが必要なので、(features, labels)Dataset.from_tensor_slices を渡し、必要なスライスのペアを取得します。

numeric_dataset = tf.data.Dataset.from_tensor_slices((numeric_features, target)) for row in numeric_dataset.take(3): print(row)
numeric_batches = numeric_dataset.shuffle(1000).batch(BATCH_SIZE) model = get_basic_model() model.fit(numeric_batches, epochs=15)

ディレクトリとしての DataFrame

型が異なるデータを処理する場合、DataFrame を単一の配列であるかのように扱うことができなくなります。TensorFlow テンソルでは、すべての要素が同じ dtype である必要があります。

したがって、この場合、各列が均一な dtype を持つ列のディクショナリとして扱う必要があります。DataFrame は配列のディクショナリによく似ているため、通常、必要なのは DataFrame を Python dict にキャストするだけです。多くの重要な TensorFlow API は、配列の (ネストされた) ディクショナリを入力としてサポートしています。

tf.data 入力パイプラインはこれを非常にうまく処理します。すべての tf.data 演算は、ディクショナリとタプルを自動的に処理するので、DataFrame からディクショナリのサンプルのデータセットを作成するには、Dataset.from_tensor_slices でスライスする前に、それをディクショナリにキャストするだけです。

numeric_dict_ds = tf.data.Dataset.from_tensor_slices((dict(numeric_features), target))

以下はデータセットの最初の 3 つのサンプルです。

for row in numeric_dict_ds.take(3): print(row)

Keras のディクショナリ

通常、Keras モデルとレイヤーは単一の入力テンソルを期待しますが、これらのクラスはディクショナリ、タプル、テンソルのネストされた構造を受け入れて返すことができます。これらの構造は「ネスト」と呼ばれます (詳細については、tf.nest モジュールを参照してください)。

ディクショナリを入力として受け入れる Keras モデルを作成するには、2 つの同等の方法があります。

1. モデルサブクラススタイル

tf.keras.Model (または tf.keras.Layer) のサブクラスを記述します。入力を直接処理し、出力を作成します。

def stack_dict(inputs, fun=tf.stack): values = [] for key in sorted(inputs.keys()): values.append(tf.cast(inputs[key], tf.float32)) return fun(values, axis=-1)
#@title class MyModel(tf.keras.Model): def __init__(self): # Create all the internal layers in init. super().__init__(self) self.normalizer = tf.keras.layers.Normalization(axis=-1) self.seq = tf.keras.Sequential([ self.normalizer, tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(1) ]) def adapt(self, inputs): # Stack the inputs and `adapt` the normalization layer. inputs = stack_dict(inputs) self.normalizer.adapt(inputs) def call(self, inputs): # Stack the inputs inputs = stack_dict(inputs) # Run them through all the layers. result = self.seq(inputs) return result model = MyModel() model.adapt(dict(numeric_features)) model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy'], run_eagerly=True)

このモデルは、トレーニング用の列のディクショナリまたはディクショナリ要素のデータセットのいずれかを受け入れることができます。

model.fit(dict(numeric_features), target, epochs=5, batch_size=BATCH_SIZE)
numeric_dict_batches = numeric_dict_ds.shuffle(SHUFFLE_BUFFER).batch(BATCH_SIZE) model.fit(numeric_dict_batches, epochs=5)

最初の 3 つのサンプルの予測は次のとおりです。

model.predict(dict(numeric_features.iloc[:3]))

2. Keras 関数型スタイル

inputs = {} for name, column in numeric_features.items(): inputs[name] = tf.keras.Input( shape=(1,), name=name, dtype=tf.float32) inputs
x = stack_dict(inputs, fun=tf.concat) normalizer = tf.keras.layers.Normalization(axis=-1) normalizer.adapt(stack_dict(dict(numeric_features))) x = normalizer(x) x = tf.keras.layers.Dense(10, activation='relu')(x) x = tf.keras.layers.Dense(10, activation='relu')(x) x = tf.keras.layers.Dense(1)(x) model = tf.keras.Model(inputs, x) model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy'], run_eagerly=True)
tf.keras.utils.plot_model(model, rankdir="LR", show_shapes=True)

モデルサブクラスと同じ方法で関数モデルをトレーニングできます。

model.fit(dict(numeric_features), target, epochs=5, batch_size=BATCH_SIZE)
numeric_dict_batches = numeric_dict_ds.shuffle(SHUFFLE_BUFFER).batch(BATCH_SIZE) model.fit(numeric_dict_batches, epochs=5)

完全なサンプル

異なる型の DataFrame を Keras に渡す場合、各列に対して固有の前処理が必要になる場合があります。この前処理は DataFrame で直接行うことができますが、モデルが正しく機能するためには、入力を常に同じ方法で前処理する必要があります。したがって、最善のアプローチは、前処理をモデルに組み込むことです。Keras 前処理レイヤーは多くの一般的なタスクをカバーしています。

前処理ヘッドを構築する

このデータセットでは、生データの「整数」特徴量の一部は実際にはカテゴリインデックスです。これらのインデックスは実際には順序付けられた数値ではありません (詳細については、データセットの説明を参照してください)。これらは順序付けされていないため、モデルに直接フィードするのは不適切です。モデルはそれらを順序付けされたものとして解釈するからです。これらの入力を使用するには、ワンホットベクトルまたは埋め込みベクトルとしてエンコードする必要があります。文字列カテゴリカル特徴量でも同じです。

注意: 同一の前処理を必要とする多くの特徴量がある場合は、前処理を適用する前にそれらを連結すると効率的です。

一方、バイナリ特徴量は、通常、エンコードまたは正規化する必要はありません。

各グループに分類される特徴量のリストを作成することから始めます。

binary_feature_names = ['sex', 'fbs', 'exang']
categorical_feature_names = ['cp', 'restecg', 'slope', 'thal', 'ca']

次に、各入力に適切な前処理を適用し、結果を連結する前処理モデルを構築します。

このセクションでは、Keras Functional API を使用して前処理を実装します。まず、データフレームの列ごとに 1 つの tf.keras.Input を作成します。

inputs = {} for name, column in df.items(): if type(column[0]) == str: dtype = tf.string elif (name in categorical_feature_names or name in binary_feature_names): dtype = tf.int64 else: dtype = tf.float32 inputs[name] = tf.keras.Input(shape=(), name=name, dtype=dtype)
inputs

入力ごとに、Keras レイヤーと TensorFlow 演算を使用していくつかの変換を適用します。各特徴量は、スカラーのバッチとして開始されます (shape=(batch,))。それぞれの出力は、tf.float32 ベクトルのバッチ (shape=(batch, n)) である必要があります。最後のステップでは、これらすべてのベクトルを連結します。

バイナリ入力

バイナリ入力は前処理を必要としないため、ベクトル軸を追加し、float32 にキャストして、前処理された入力のリストに追加します。

preprocessed = [] for name in binary_feature_names: inp = inputs[name] inp = inp[:, tf.newaxis] float_value = tf.cast(inp, tf.float32) preprocessed.append(float_value) preprocessed

数値入力

前のセクションと同様に、これらの数値入力は、使用する前に tf.keras.layers.Normalization レイヤーを介して実行する必要があります。違いは、ここでは dict として入力されることです。以下のコードは、DataFrame から数値の特徴量を収集し、それらをスタックし、Normalization.adapt メソッドに渡します。

normalizer = tf.keras.layers.Normalization(axis=-1) normalizer.adapt(stack_dict(dict(numeric_features)))

以下のコードは、数値特徴量をスタックし、それらを正規化レイヤーで実行します。

numeric_inputs = {} for name in numeric_feature_names: numeric_inputs[name]=inputs[name] numeric_inputs = stack_dict(numeric_inputs) numeric_normalized = normalizer(numeric_inputs) preprocessed.append(numeric_normalized) preprocessed

カテゴリカル特徴量

カテゴリカル特徴量を使用するには、最初にそれらをバイナリベクトルまたは埋め込みのいずれかにエンコードする必要があります。これらの特徴量には少数のカテゴリしか含まれていないため、tf.keras.layers.StringLookup および tf.keras.layers.IntegerLookup レイヤーの両方でサポートされている output_mode='one_hot' オプションを使用して、入力をワンホットベクトルに直接変換します。

次に、これらのレイヤーがどのように機能するかの例を示します。

vocab = ['a','b','c'] lookup = tf.keras.layers.StringLookup(vocabulary=vocab, output_mode='one_hot') lookup(['c','a','a','b','zzz'])
vocab = [1,4,7,99] lookup = tf.keras.layers.IntegerLookup(vocabulary=vocab, output_mode='one_hot') lookup([-1,4,1])

各入力の語彙を決定するには、その語彙をワンホットベクトルに変換するレイヤーを作成します。

for name in categorical_feature_names: vocab = sorted(set(df[name])) print(f'name: {name}') print(f'vocab: {vocab}\n') if type(vocab[0]) is str: lookup = tf.keras.layers.StringLookup(vocabulary=vocab, output_mode='one_hot') else: lookup = tf.keras.layers.IntegerLookup(vocabulary=vocab, output_mode='one_hot') x = inputs[name][:, tf.newaxis] x = lookup(x) preprocessed.append(x)

前処理ヘッドを組み立てる

この時点で、preprocessed はすべての前処理結果の Python リストであり、各結果は (batch_size, depth) の形状をしています。

preprocessed

前処理されたすべての特徴量を depth 軸に沿って連結し、各ディクショナリのサンプルを単一のベクトルに変換します。ベクトルには、カテゴリカル特徴量、数値特徴量、およびカテゴリワンホット特徴量が含まれています。

preprocesssed_result = tf.concat(preprocessed, axis=-1) preprocesssed_result

次に、その計算からモデルを作成して、再利用できるようにします。

preprocessor = tf.keras.Model(inputs, preprocesssed_result)
tf.keras.utils.plot_model(preprocessor, rankdir="LR", show_shapes=True)

プリプロセッサをテストするには、DataFrame.iloc アクセサを使用して、DataFrame から最初のサンプルをスライスします。次に、それをディクショナリに変換し、ディクショナリをプリプロセッサに渡します。結果は、バイナリ特徴量、正規化された数値特徴量、およびワンホットカテゴリカル特徴量をこの順序で含む単一のベクトルになります。

preprocessor(dict(df.iloc[:1]))

モデルを作成して訓練する

次に、モデルの本体を作成します。前の例と同じ構成を使用します。分類には、いくつかの Dense 正規化線形レイヤーと Dense(1) 出力レイヤーを使用します。

body = tf.keras.Sequential([ tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(1) ])

次に、Keras 関数型 API を使用して 2 つの部分を組み合わせます。

inputs
x = preprocessor(inputs) x
result = body(x) result
model = tf.keras.Model(inputs, result) model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy'])

このモデルは、入力のディクショナリを想定しています。データを渡す最も簡単な方法は、DataFrame を dict に変換し、その dict を x 引数として Model.fit に渡すことです。

history = model.fit(dict(df), target, epochs=5, batch_size=BATCH_SIZE)

tf.data を使用しても同様に機能します。

ds = tf.data.Dataset.from_tensor_slices(( dict(df), target )) ds = ds.batch(BATCH_SIZE)
import pprint for x, y in ds.take(1): pprint.pprint(x) print() print(y)
history = model.fit(ds, epochs=5)