生成モデリング
生成モデルとは
確率統計レベル: いくつかの暗黙のパラメータを与えて、オブザベーションをランダムに生成できるモデルは、「生成モデル」と呼ばれます。これはオブザベーションと週データ系列に連続確率分布を割り当てます。
機械学習レベル:変数の確率密度関数に基づくデータのサンプリングなど、データを直接モデル化。ベイズアルゴリズムでは、企業と確率分布P(x,y)を直接モデル化し、ベイズ式を用いてP(y|x)を解きます。
生成モデルによる分類
タイプI:データの正確な分布関数を完全に表す
タイプII:正確な分布関数を完全に表現する方法はありませんが、正確な分布関数が曖昧な新しいデータを生成することはできます。
機械学習では、オートエンコーダAEであれ、変分オートエンコーダVAEであれ、生成的敵対ネットワークGANであれ、それらはすべて2番目のカテゴリーに属します。新しいデータを生成することは、ほとんどの生成モデルの中核的な目標でもあります。
セルフエンコーダの原理
原理
まず、教師あり学習におけるニューラルネットワークの機能を考えてみましょう:
は 入力特徴ベクトルの長さで、出力特徴ベクトルの長さです。分類問題では、ネットワークモデルは、長さの入力特徴ベクトル 𝒙 を長さの出力ベクトル 𝒐 に変換します。 特徴のダウンスケール処理は、機械学習ファイル圧縮、データ前処理など、幅広い応用があります。最も一般的な次元削減アルゴリズムは主成分分析(PCA)であり、共分散行列を特徴量に分解することでデータの主成分を得ますが、PCAは本質的に線形変換であり、特徴量を抽出する能力は極めて限定的です。
では、ニューラルネットワークの強力な非線形表現を利用して、データの低次元表現を学習できるのでしょうか?この問題の核心は、一般的に神 経の学習には明示的にラベル付けされたデータが必要ですが、教師なしデータには追加のラベリング情報はなく、データ L_1D499そのものしかないということです。
したがって、データ𝒙そのものをネットワーク学習のための監視信号として使用することができ、ニューラルネットワークがマッピングを学習することができます。
ネットワークを2つの部分に分割すると、前側のサブネットワークは写像関係を学習しようとし、後側のサブネットワークは写像関係を学習しようとします。ᑔᜃは高次元の入力ǔを低次元の隠れ変数ǔにエンコードするデータエンコードプロセスで、エンコーダーネットワークと呼ばれます。エンコードされた入力ᵉを高次元の𝒙にデコードするプロセスで、デコーダー・ネットワークと呼ばれます。
エンコーダーとデコーダーは一緒になって入力データのエンコードとデコードのプロセスを完了します。
ディープニューラルネットワークがパラメータ化と機能に使用される場合、それはディープオートエンコーダと呼ばれます。
自己符号化の最適化
自己エンコーダは、入力を隠れベクトルに変換し、デコーダを通して.
デコーダの出力が元の入力を完全または近似的に復元することが望まれます:
ここで、 𝒙 と 𝒙 の間の距離メトリックを表し、再構成誤差関数と呼ばれます。最も一般的な測定基準は、次のように計算される2乗ユークリッド距離です:
ディープニューラルネットワークの非線形特徴抽出能力により、セルフエンコーダは良好なデータ表現を得ることができます。入力 𝒙 をより完璧に復元することができます。
この時に活躍できるのがセルフコーダです。_MNIST
データセットの紹介
Fashion_MNISTデータセットは、機械学習の分野では非常に古典的なデータセットで、これを直接読み込む最も簡単な方法は、次のコードを使うことです。
import tensorflow as tf
(X_train, y_train), (X_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()
print(X_train.shape, y_train.shape) # (60000, 28, 28) (60000,)
print(X_test.shape, y_test.shape) # (10000, 28, 28) (10000,)
データセットは60,000個のトレーニング用サンプルと10,000個のテスト用サンプルで構成され、各サンプルは28×28ピクセルのグレースケールイメージです。
import matplotlib.pyplot as plt
plt.figure()
plt.imshow(X_train[0])
plt.colorbar()
plt.grid(False)
plt.show()
最初の25枚のイメージを印刷
# ピクセル値を0-1にスケーリングする
X_train = X_train / 255.0
X_test = X_test / 255.0
# すべての分類ラベル
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
plt.figure(figsize=(10,10))
for i in range(25):
plt.subplot(5,5,i+1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(X_train[i], cmap=plt.cm.binary)
plt.xlabel(class_names[y_train[i]])
セルフエンコーダ
セルフエンコーダー・ニューラルネットワークの構築
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train, x_test = x_train.astype(np.float32) / 255., x_test.astype(np.float32) / 255.
train_db = tf.data.Dataset.from_tensor_slices(x_train)
train_db = train_db.shuffle(buffer_size=512).batch(512)
test_db = tf.data.Dataset.from_tensor_slices(x_test)
test_db = test_db.batch(512)
class AutoEncoder(keras.Model):
def __init__(self):
super(AutoEncoder, self).__init__()
# Encoders
self.encoder = Sequential([
layers.Dense(256, activation=tf.nn.relu),
layers.Dense(128, activation=tf.nn.relu),
layers.Dense(20)
])
# Decoders
self.decoder = Sequential([
layers.Dense(128, activation=tf.nn.relu),
layers.Dense(256, activation=tf.nn.relu),
layers.Dense(784)
])
# 前方計算
def call(self, inputs, training=None):
# [b, 784] => [b, 20]
h = self.encoder(inputs)
# [b, 20] => [b, 784]
x_hat = self.decoder(h)
return x_hat
# セルフエンコーダーオブジェクトを作る
model = AutoEncoder()
model.build(input_shape=(None, 28 * 28))
# コンフィギュレーション・オプティマイザー
optimizer = tf.optimizers.Adam(learning_rate=1e-3)
# 学習を開始する
for epoch in range(20):
for step, x in enumerate(train_db):
#[b, 28, 28] => [b, 784]
x = tf.reshape(x, [-1, 28 * 28])
# グラデーション・レコーダーを作る
with tf.GradientTape() as tape:
# 前方計算
x_rec_logits = model(x)
# 損失関数を計算する
rec_loss = tf.losses.binary_crossentropy(x, x_rec_logits, from_logits=True)
rec_loss = tf.reduce_mean(rec_loss)
# 自動微分
grads = tape.gradient(rec_loss, model.trainable_variables)
# ネットワークを更新する
optimizer.apply_gradients(zip(grads, model.trainable_variables))
# 学習誤差を印刷する
print("epoch: ", epoch, "loss: ", float(rec_loss))
# 印刷すると生成されたイメージが表示される
x = next(iter(test_db))
logits = model(tf.reshape(x, [-1, 28 * 28]))
# 出力値を画素値に変換する
x_hat = tf.sigmoid(logits)
# [b, 784] => [b, 28, 28] 元のデータ形式を復元する
x_hat = tf.reshape(x_hat, [-1, 28, 28])
# [b, 28, 28] => [2b, 28, 28]
# 最初の50枚の入力イメージ+再構成の最初の50枚のイメージはマージされる
x_concat = tf.concat([x[:50], x_hat[:50]], axis=0)
# 0~255の範囲に回復する
x_concat = x_concat.numpy() * 255.
# 整数に変換する
x_concat = x_concat.astype(np.uint8)
printImage(x_concat)
# 上5行が原イメージ、下5行が主成分を用いて復元したイメージである。
数回の繰り返しの後、再構成結果は以下のようになります。上の5行が元のイメージで、下の5行が再構成されたイメージです。
写真を見てお分かりのように、自己符号化モデルにアップロードされたばかりのイメージは、基本的に圧縮、そして解凍のプロセスを経ています。圧縮すると元イメージの画質が落ち、解凍すると元イメージの情報をすべて含んだファイルが少量で復元されます。では、なぜこのようなことが必要なのでしょうか?ハイビジョンイメージなど、ニューラルネットワークが大量の情報を入力しなければならない場合、入力イメージの数は数千万枚に達することもあり、その入力データ量からニューラルネットワークに直接学習させるのは非常に手間がかかり、魅力的な作業ではないので、圧縮すればいいのではないかと考えられたのです。原イメージの中から最も代表的な情報を抽出し、入力の情報量を減らし、その減らした情報をニューラルネットワークに投入して学習させることで、学習が容易になるため、この時に自己符号化が活躍できるわけです。





