Keras

高レベルなディープラーニングAPI。TensorFlow 2.0以降に統合され、直感的で使いやすいインターフェースを提供。プロトタイピングから本番運用まで対応し、初学者から専門家まで幅広く利用される。

PythonディープラーニングニューラルネットワークTensorFlow高レベルAPI

GitHub概要

keras-team/keras

Deep Learning for humans

ホームページ:https://keras.io/
スター61,876
ウォッチ2,567
フォーク19,456
作成日:2014年3月28日
言語:Python
ライセンス:Apache License 2.0

トピックス

kerasdeep-learningmachine-learningneural-networkspythontensorflowaiapi

スター履歴

keras-team/keras Star History
データ取得日時: Invalid Date

フレームワーク

Keras

概要

Kerasは、TensorFlow、PyTorch、JAXの高レベルAPIとして機能するニューラルネットワークライブラリです。

詳細

Keras(ケラス)は2015年にFrançois Cholletによって開発された、ディープラーニングのための高レベルニューラルネットワークAPIです。現在はTensorFlowに統合され、tf.kerasとして提供されています。シンプルで直感的なAPIにより、研究者と開発者がディープラーニングモデルを迅速にプロトタイピングできることを目的としています。ユーザーフレンドリーな設計、モジュラー性、拡張性を重視し、初心者でも簡単にニューラルネットワークを構築できます。CNN、RNN、トランスフォーマーなど様々なアーキテクチャをサポートし、Sequential API、Functional API、Subclassing APIの3つの構築方法を提供します。プロトタイピングから本格的な研究、プロダクション展開まで幅広い用途で使用され、教育現場でのディープラーニング入門にも最適です。豊富な事前学習済みモデル、各種コールバック機能、可視化ツールにより、効率的なモデル開発を支援します。

メリット・デメリット

メリット

  • 直感的なAPI: シンプルで理解しやすい高レベルインターフェース
  • 迅速な開発: 最小限のコードでニューラルネットワークを構築
  • TensorFlow統合: TensorFlowエコシステムとの完全な互換性
  • 豊富な事前学習モデル: ImageNet学習済みモデルなど多数提供
  • 3つの構築方法: Sequential、Functional、Subclassing APIで柔軟性
  • 教育向け: ディープラーニング学習に最適な設計
  • 豊富なドキュメント: 詳細なガイドとサンプルコード

デメリット

  • 抽象化レベル: 低レベル制御が困難な場合がある
  • TensorFlow依存: TensorFlowの制約を受ける
  • カスタマイゼーション: 高度なカスタムレイヤーの実装が複雑
  • デバッグ: 抽象化により内部動作の理解が困難
  • 最新研究: 最新のアーキテクチャ実装に時間がかかる場合
  • パフォーマンス: 低レベルAPIより実行速度が劣る場合がある

主要リンク

書き方の例

Hello World

import tensorflow as tf
from tensorflow import keras
import numpy as np

# Kerasのバージョン確認
print(f"TensorFlow version: {tf.__version__}")
print(f"Keras version: {keras.__version__}")

# 簡単なSequentialモデル
model = keras.Sequential([
    keras.layers.Dense(64, activation='relu', input_shape=(10,)),
    keras.layers.Dense(32, activation='relu'),
    keras.layers.Dense(1, activation='sigmoid')
])

# モデルの概要表示
model.summary()

# コンパイル
model.compile(
    optimizer='adam',
    loss='binary_crossentropy',
    metrics=['accuracy']
)

# サンプルデータでテスト
X_sample = np.random.random((100, 10))
y_sample = np.random.randint(2, size=(100, 1))

# 簡単な学習
history = model.fit(X_sample, y_sample, epochs=5, verbose=1)

# 予測
predictions = model.predict(X_sample[:5])
print(f"Predictions: {predictions.flatten()}")

CNNによる画像分類

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt

# CIFAR-10データセットの読み込み
(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data()

# データの前処理
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)

print(f"Training data shape: {x_train.shape}")
print(f"Test data shape: {x_test.shape}")

# CNNモデルの構築
model = keras.Sequential([
    # 第1ブロック
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)),
    layers.BatchNormalization(),
    layers.Conv2D(32, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Dropout(0.25),
    
    # 第2ブロック
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.BatchNormalization(),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Dropout(0.25),
    
    # 第3ブロック
    layers.Conv2D(128, (3, 3), activation='relu'),
    layers.BatchNormalization(),
    layers.Dropout(0.25),
    
    # 分類層
    layers.Flatten(),
    layers.Dense(512, activation='relu'),
    layers.BatchNormalization(),
    layers.Dropout(0.5),
    layers.Dense(10, activation='softmax')
])

# モデルのコンパイル
model.compile(
    optimizer=keras.optimizers.Adam(learning_rate=0.001),
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

# モデル構造の表示
model.summary()

# コールバックの設定
callbacks = [
    keras.callbacks.EarlyStopping(patience=5, restore_best_weights=True),
    keras.callbacks.ReduceLROnPlateau(patience=3, factor=0.5, min_lr=1e-7),
    keras.callbacks.ModelCheckpoint('best_model.h5', save_best_only=True)
]

# 学習の実行
history = model.fit(
    x_train, y_train,
    batch_size=128,
    epochs=50,
    validation_data=(x_test, y_test),
    callbacks=callbacks,
    verbose=1
)

# 評価
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=0)
print(f'Test accuracy: {test_acc:.4f}')

Functional APIによる複雑なモデル

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

# 入力層の定義
input_layer = keras.Input(shape=(224, 224, 3), name='image_input')

# バックボーンネットワーク (ResNet風)
def residual_block(x, filters, kernel_size=3, stride=1):
    shortcut = x
    
    # メインパス
    x = layers.Conv2D(filters, kernel_size, strides=stride, padding='same')(x)
    x = layers.BatchNormalization()(x)
    x = layers.ReLU()(x)
    
    x = layers.Conv2D(filters, kernel_size, padding='same')(x)
    x = layers.BatchNormalization()(x)
    
    # ショートカット接続
    if stride != 1 or shortcut.shape[-1] != filters:
        shortcut = layers.Conv2D(filters, 1, strides=stride, padding='same')(shortcut)
        shortcut = layers.BatchNormalization()(shortcut)
    
    x = layers.Add()([x, shortcut])
    x = layers.ReLU()(x)
    
    return x

# 特徴抽出部
x = layers.Conv2D(64, 7, strides=2, padding='same')(input_layer)
x = layers.BatchNormalization()(x)
x = layers.ReLU()(x)
x = layers.MaxPooling2D(3, strides=2, padding='same')(x)

# Residualブロック
x = residual_block(x, 64)
x = residual_block(x, 64)
x = residual_block(x, 128, stride=2)
x = residual_block(x, 128)
x = residual_block(x, 256, stride=2)
x = residual_block(x, 256)

# グローバル平均プーリング
feature_vector = layers.GlobalAveragePooling2D(name='feature_vector')(x)

# 分類ヘッド
classification_output = layers.Dense(1000, activation='softmax', name='classification')(feature_vector)

# 回帰ヘッド(例:年齢予測)
regression_output = layers.Dense(1, activation='linear', name='regression')(feature_vector)

# モデルの作成
model = keras.Model(
    inputs=input_layer,
    outputs=[classification_output, regression_output],
    name='multi_output_model'
)

# モデルのコンパイル(マルチタスク)
model.compile(
    optimizer='adam',
    loss={
        'classification': 'categorical_crossentropy',
        'regression': 'mse'
    },
    loss_weights={
        'classification': 1.0,
        'regression': 0.5
    },
    metrics={
        'classification': ['accuracy'],
        'regression': ['mae']
    }
)

model.summary()

カスタムレイヤーとモデル

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

# カスタムレイヤーの定義
class AttentionLayer(layers.Layer):
    def __init__(self, units, **kwargs):
        super(AttentionLayer, self).__init__(**kwargs)
        self.units = units
        
    def build(self, input_shape):
        self.W = self.add_weight(
            shape=(input_shape[-1], self.units),
            initializer='random_normal',
            trainable=True,
            name='attention_weights'
        )
        self.b = self.add_weight(
            shape=(self.units,),
            initializer='zeros',
            trainable=True,
            name='attention_bias'
        )
        self.u = self.add_weight(
            shape=(self.units,),
            initializer='random_normal',
            trainable=True,
            name='attention_context'
        )
        super(AttentionLayer, self).build(input_shape)
    
    def call(self, inputs):
        # アテンション機構の計算
        score = tf.nn.tanh(tf.tensordot(inputs, self.W, axes=1) + self.b)
        attention_weights = tf.nn.softmax(tf.tensordot(score, self.u, axes=1), axis=1)
        context_vector = tf.reduce_sum(inputs * tf.expand_dims(attention_weights, -1), axis=1)
        return context_vector, attention_weights
    
    def get_config(self):
        config = super(AttentionLayer, self).get_config()
        config.update({'units': self.units})
        return config

# カスタムモデルクラス
class TextClassificationModel(keras.Model):
    def __init__(self, vocab_size, embedding_dim, max_length, num_classes):
        super(TextClassificationModel, self).__init__()
        self.embedding = layers.Embedding(vocab_size, embedding_dim, input_length=max_length)
        self.lstm = layers.LSTM(128, return_sequences=True)
        self.attention = AttentionLayer(64)
        self.dropout = layers.Dropout(0.5)
        self.classifier = layers.Dense(num_classes, activation='softmax')
    
    def call(self, inputs, training=None):
        x = self.embedding(inputs)
        x = self.lstm(x)
        context_vector, attention_weights = self.attention(x)
        x = self.dropout(context_vector, training=training)
        return self.classifier(x)

# モデルのインスタンス化
model = TextClassificationModel(
    vocab_size=10000,
    embedding_dim=100,
    max_length=500,
    num_classes=5
)

# モデルのコンパイル
model.compile(
    optimizer='adam',
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

# ダミーデータでモデルの形状を確定
dummy_input = tf.random.uniform((1, 500), maxval=10000, dtype=tf.int32)
_ = model(dummy_input)

model.summary()

転移学習

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.applications import ResNet50

# 事前学習済みモデルの読み込み
base_model = ResNet50(
    weights='imagenet',
    include_top=False,
    input_shape=(224, 224, 3)
)

# ベースモデルの重みを凍結
base_model.trainable = False

# カスタム分類器の追加
model = keras.Sequential([
    base_model,
    layers.GlobalAveragePooling2D(),
    layers.Dropout(0.2),
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.2),
    layers.Dense(10, activation='softmax')  # 10クラス分類
])

# 初期学習(特徴抽出)
model.compile(
    optimizer=keras.optimizers.Adam(1e-3),
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

print("Phase 1: Feature extraction")
# history1 = model.fit(train_dataset, epochs=10, validation_data=val_dataset)

# ファインチューニング
base_model.trainable = True

# 最後の数層のみ学習可能にする
for layer in base_model.layers[:-20]:
    layer.trainable = False

# 低い学習率で再コンパイル
model.compile(
    optimizer=keras.optimizers.Adam(1e-5),
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

print("Phase 2: Fine-tuning")
# history2 = model.fit(train_dataset, epochs=10, validation_data=val_dataset)

model.summary()

モデルの保存と読み込み

import tensorflow as tf
from tensorflow import keras

# モデルの構築
model = keras.Sequential([
    keras.layers.Dense(64, activation='relu', input_shape=(20,)),
    keras.layers.Dropout(0.3),
    keras.layers.Dense(32, activation='relu'),
    keras.layers.Dense(10, activation='softmax')
])

model.compile(
    optimizer='adam',
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

# サンプルデータで学習
import numpy as np
X_train = np.random.random((1000, 20))
y_train = keras.utils.to_categorical(np.random.randint(10, size=(1000, 1)), 10)

model.fit(X_train, y_train, epochs=10, verbose=0)

# 1. モデル全体の保存(推奨)
model.save('complete_model.keras')

# 2. HDF5形式での保存
model.save('model.h5')

# 3. 重みのみ保存
model.save_weights('model_weights.h5')

# 4. モデル構造の保存(JSON)
model_json = model.to_json()
with open('model_architecture.json', 'w') as f:
    f.write(model_json)

# モデルの読み込み
# 1. 完全なモデルの読み込み
loaded_model = keras.models.load_model('complete_model.keras')

# 2. HDF5形式からの読み込み
loaded_model_h5 = keras.models.load_model('model.h5')

# 3. 構造と重みを別々に読み込み
with open('model_architecture.json', 'r') as f:
    model_json = f.read()

loaded_model_from_json = keras.models.model_from_json(model_json)
loaded_model_from_json.load_weights('model_weights.h5')
loaded_model_from_json.compile(
    optimizer='adam',
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

# SavedModel形式での保存・読み込み
tf.saved_model.save(model, 'saved_model_dir')
loaded_saved_model = tf.saved_model.load('saved_model_dir')

# 予測の確認
test_input = np.random.random((5, 20))
original_pred = model.predict(test_input)
loaded_pred = loaded_model.predict(test_input)

print("予測結果の一致:", np.allclose(original_pred, loaded_pred))
print(f"元のモデル精度: {model.evaluate(X_train, y_train, verbose=0)[1]:.4f}")
print(f"読み込み後精度: {loaded_model.evaluate(X_train, y_train, verbose=0)[1]:.4f}")