<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Copyright 2020 The TensorFlow Authors.
Step1:  オートエンコーダの基礎
<table class="tfo-notebook-buttons" align="left">
  <td>     <a target="_blank" href="https
Step2:  データセットを読み込む
まず、Fashion MNIST データセットを使用して基本的なオートエンコーダーをトレーニングします。このデータセットの各画像は 28x28 ピクセルです。
Step3:  最初の例：オートエンコーダの基本
次の2つの高密度レイヤーでオートエンコーダーを定義します。encoder は、画像を 64 次元の潜在ベクトルに圧縮します。decoder は、潜在空間から元の画像を再構築します。
モデルを定義するには、Keras Model Subclassing API を使用します。
Step4:  入力とターゲットの両方として x_train を使用してモデルをトレーニングします。encoder は、データセットを 784 次元から潜在空間に圧縮することを学習し、decoder は元の画像を再構築することを学習します。
Step5:  モデルがトレーニングされたので、テストセットから画像をエンコードおよびデコードしてモデルをテストします。
Step6:  2番目の例：画像のノイズ除去
オートエンコーダは、画像からノイズを除去するようにトレーニングすることもできます。 次のセクションでは、各画像にランダムノイズを適用して、ノイズの多いバージョンの FashionMNIST データセットを作成します。次に、ノイズの多い画像を入力として使用し、元の画像をターゲットとして使用して、オートエンコーダーをトレーニングします。
データセットを再インポートして、以前に行った変更を省略しましょう。
Step7:  画像にランダムノイズを追加します
Step8:  ノイズの多い画像をプロットします。
Step9:  畳み込みオートエンコーダーを定義します。
この例では、encoder の Conv2D レイヤーと、decoder の Conv2DTranspose レイヤーを使用して畳み込みオートエンコーダーをトレーニングします。
Step10:  エンコーダーの概要を見てみましょう。画像が 28x28 から 7x7 にダウンサンプリングされていることに注目してください。
Step11:  デコーダーは画像を 7x7 から 28x28 にアップサンプリングします。
Step12:  オートエンコーダにより生成されたノイズの多い画像とノイズ除去された画像の両方をプロットします。
Step13:  3番目の例：異常検出
概要
この例では、オートエンコーダーをトレーニングして、ECG5000 データセットの異常を検出します。このデータセットには、5,000 の心電図が含まれ、それぞれに 140 のデータポイントがあります。データセットの簡略化されたバージョンを使用します。各例には、0（異常なリズムに対応）または1（正常なリズムに対応）のいずれかのラベルが付けられています。ここでは異常なリズムを特定することに興味があります。
注意：これはラベル付きのデータセットであるため、教師あり学習の問題と見なせます。この例の目的は、ラベルが使用できない、より大きなデータセットに適用できる異常検出の概念を説明することです（たとえば、数千の正常なリズムがあり、異常なリズムが少数しかない場合）。
オートエンコーダーを使用すると、どのようにして異常を検出できるのでしょうか？オートエンコーダは、再構築エラーを最小限に抑えるようにトレーニングされていることを思い出してください。オートエンコーダーは通常のリズムでのみトレーニングし、それを使用してすべてのデータを再構築します。私たちの仮説は、異常なリズムはより高い再構成エラーを持つだろうということです。次に、再構成エラーが固定しきい値を超えた場合、リズムを異常として分類します。
ECG データを読み込む
使用するデータセットは、timeseriesclassification.com のデータセットに基づいています。
Step14:  データを [0,1] に正規化します。
Step15:  このデータセットで 1 としてラベル付けされている通常のリズムのみを使用して、オートエンコーダーをトレーニングします。正常なリズムを異常なリズムから分離します。
Step16:  正常な ECG をプロットします。
Step17:  異常な ECG をプロットします。
Step18:  モデルを構築する
Step19:  オートエンコーダは通常の ECG のみを使用してトレーニングされますが、完全なテストセットを使用して評価されることに注意してください。
Step20:  再構成エラーが正常なトレーニング例からの1標準偏差より大きい場合、ECG を異常として分類します。まず、トレーニングセットからの正常な ECG、オートエンコーダーによりエンコードおよびデコードされた後の再構成、および再構成エラーをプロットします。
Step21:  異常なテストサンプルで同様にプロットを作成します。
Step22:  異常を検出します
再構成損失が指定してしきい値より大きいかどうかを計算することにより、異常を検出します。このチュートリアルでは、トレーニングセットから正常なサンプルの平均平均誤差を計算し、再構成誤差がトレーニングセットからの1標準偏差よりも大きい場合、以降のサンプルを異常として分類します。
トレーニングセットからの通常の ECG に再構成エラーをプロットします
Step23:  平均より1標準偏差上のしきい値を選択します。
Step24:  注意
Step25:  再構成エラーがしきい値よりも大きい場合は、ECG を異常として分類します。
<ASSISTANT_TASK:>
Python Code:
#@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.
Explanation: Copyright 2020 The TensorFlow Authors.
End of explanation
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import tensorflow as tf
from sklearn.metrics import accuracy_score, precision_score, recall_score
from sklearn.model_selection import train_test_split
from tensorflow.keras import layers, losses
from tensorflow.keras.datasets import fashion_mnist
from tensorflow.keras.models import Model
Explanation: オートエンコーダの基礎
<table class="tfo-notebook-buttons" align="left">
  <td>     <a target="_blank" href="https://www.tensorflow.org/tutorials/generative/autoencoder"><img src="https://www.tensorflow.org/images/tf_logo_32px.png">TensorFlow.org で表示</a> </td>
  <td>     <a target="_blank" href="https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ja/tutorials/generative/autoencoder.ipynb"><img src="https://www.tensorflow.org/images/colab_logo_32px.png">Google Colab で実行</a> </td>
  <td><a target="_blank" href="https://github.com/tensorflow/docs-l10n/blob/master/site/ja/tutorials/generative/autoencoder.ipynb"><img src="https://www.tensorflow.org/images/GitHub-Mark-32px.png"> GitHub でソースを表示</a></td>
  <td>     <a href="https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ja/tutorials/generative/autoencoder.ipynb"><img src="https://www.tensorflow.org/images/download_logo_32px.png">ノートブックをダウンロード</a> </td>
</table>
このチュートリアルでは、基本、画像のノイズ除去、異常検出の3つの例を使用してオートエンコーダを紹介します。
オートエンコーダは、入力を出力にコピーするようにトレーニングされた特殊なタイプのニューラルネットワークです。たとえば、手書きの数字の画像が与えられた場合、オートエンコーダは最初に画像を低次元の潜在表現にエンコードし、次に潜在表現をデコードして画像に戻します。オートエンコーダは、再構成エラーを最小限に抑えながらデータを圧縮することを学習します。
オートエンコーダの詳細については、Ian Goodfellow、Yoshua Bengio、AaronCourville によるディープラーニングの第 14 章を参照してください。
TensorFlow とその他のライブラリをインポートする
End of explanation
(x_train, _), (x_test, _) = fashion_mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
print (x_train.shape)
print (x_test.shape)
Explanation: データセットを読み込む
まず、Fashion MNIST データセットを使用して基本的なオートエンコーダーをトレーニングします。このデータセットの各画像は 28x28 ピクセルです。
End of explanation
latent_dim = 64 
class Autoencoder(Model):
  def __init__(self, latent_dim):
    super(Autoencoder, self).__init__()
    self.latent_dim = latent_dim   
    self.encoder = tf.keras.Sequential([
      layers.Flatten(),
      layers.Dense(latent_dim, activation='relu'),
    ])
    self.decoder = tf.keras.Sequential([
      layers.Dense(784, activation='sigmoid'),
      layers.Reshape((28, 28))
    ])
  def call(self, x):
    encoded = self.encoder(x)
    decoded = self.decoder(encoded)
    return decoded
  
autoencoder = Autoencoder(latent_dim) 
autoencoder.compile(optimizer='adam', loss=losses.MeanSquaredError())
Explanation: 最初の例：オートエンコーダの基本
次の2つの高密度レイヤーでオートエンコーダーを定義します。encoder は、画像を 64 次元の潜在ベクトルに圧縮します。decoder は、潜在空間から元の画像を再構築します。
モデルを定義するには、Keras Model Subclassing API を使用します。
End of explanation
autoencoder.fit(x_train, x_train,
                epochs=10,
                shuffle=True,
                validation_data=(x_test, x_test))
Explanation: 入力とターゲットの両方として x_train を使用してモデルをトレーニングします。encoder は、データセットを 784 次元から潜在空間に圧縮することを学習し、decoder は元の画像を再構築することを学習します。
End of explanation
encoded_imgs = autoencoder.encoder(x_test).numpy()
decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()
n = 10
plt.figure(figsize=(20, 4))
for i in range(n):
  # display original
  ax = plt.subplot(2, n, i + 1)
  plt.imshow(x_test[i])
  plt.title("original")
  plt.gray()
  ax.get_xaxis().set_visible(False)
  ax.get_yaxis().set_visible(False)
  # display reconstruction
  ax = plt.subplot(2, n, i + 1 + n)
  plt.imshow(decoded_imgs[i])
  plt.title("reconstructed")
  plt.gray()
  ax.get_xaxis().set_visible(False)
  ax.get_yaxis().set_visible(False)
plt.show()
Explanation: モデルがトレーニングされたので、テストセットから画像をエンコードおよびデコードしてモデルをテストします。
End of explanation
(x_train, _), (x_test, _) = fashion_mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]
print(x_train.shape)
Explanation: 2番目の例：画像のノイズ除去
オートエンコーダは、画像からノイズを除去するようにトレーニングすることもできます。 次のセクションでは、各画像にランダムノイズを適用して、ノイズの多いバージョンの FashionMNIST データセットを作成します。次に、ノイズの多い画像を入力として使用し、元の画像をターゲットとして使用して、オートエンコーダーをトレーニングします。
データセットを再インポートして、以前に行った変更を省略しましょう。
End of explanation
noise_factor = 0.2
x_train_noisy = x_train + noise_factor * tf.random.normal(shape=x_train.shape) 
x_test_noisy = x_test + noise_factor * tf.random.normal(shape=x_test.shape) 
x_train_noisy = tf.clip_by_value(x_train_noisy, clip_value_min=0., clip_value_max=1.)
x_test_noisy = tf.clip_by_value(x_test_noisy, clip_value_min=0., clip_value_max=1.)
Explanation: 画像にランダムノイズを追加します
End of explanation
n = 10
plt.figure(figsize=(20, 2))
for i in range(n):
    ax = plt.subplot(1, n, i + 1)
    plt.title("original + noise")
    plt.imshow(tf.squeeze(x_test_noisy[i]))
    plt.gray()
plt.show()
Explanation: ノイズの多い画像をプロットします。
End of explanation
class Denoise(Model):
  def __init__(self):
    super(Denoise, self).__init__()
    self.encoder = tf.keras.Sequential([
      layers.Input(shape=(28, 28, 1)),
      layers.Conv2D(16, (3, 3), activation='relu', padding='same', strides=2),
      layers.Conv2D(8, (3, 3), activation='relu', padding='same', strides=2)])
    self.decoder = tf.keras.Sequential([
      layers.Conv2DTranspose(8, kernel_size=3, strides=2, activation='relu', padding='same'),
      layers.Conv2DTranspose(16, kernel_size=3, strides=2, activation='relu', padding='same'),
      layers.Conv2D(1, kernel_size=(3, 3), activation='sigmoid', padding='same')])
  def call(self, x):
    encoded = self.encoder(x)
    decoded = self.decoder(encoded)
    return decoded
autoencoder = Denoise()
autoencoder.compile(optimizer='adam', loss=losses.MeanSquaredError())
autoencoder.fit(x_train_noisy, x_train,
                epochs=10,
                shuffle=True,
                validation_data=(x_test_noisy, x_test))
Explanation: 畳み込みオートエンコーダーを定義します。
この例では、encoder の Conv2D レイヤーと、decoder の Conv2DTranspose レイヤーを使用して畳み込みオートエンコーダーをトレーニングします。
End of explanation
autoencoder.encoder.summary()
Explanation: エンコーダーの概要を見てみましょう。画像が 28x28 から 7x7 にダウンサンプリングされていることに注目してください。
End of explanation
autoencoder.decoder.summary()
Explanation: デコーダーは画像を 7x7 から 28x28 にアップサンプリングします。
End of explanation
encoded_imgs = autoencoder.encoder(x_test_noisy).numpy()
decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()
n = 10
plt.figure(figsize=(20, 4))
for i in range(n):
    # display original + noise
    ax = plt.subplot(2, n, i + 1)
    plt.title("original + noise")
    plt.imshow(tf.squeeze(x_test_noisy[i]))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
    # display reconstruction
    bx = plt.subplot(2, n, i + n + 1)
    plt.title("reconstructed")
    plt.imshow(tf.squeeze(decoded_imgs[i]))
    plt.gray()
    bx.get_xaxis().set_visible(False)
    bx.get_yaxis().set_visible(False)
plt.show()
Explanation: オートエンコーダにより生成されたノイズの多い画像とノイズ除去された画像の両方をプロットします。
End of explanation
# Download the dataset
dataframe = pd.read_csv('http://storage.googleapis.com/download.tensorflow.org/data/ecg.csv', header=None)
raw_data = dataframe.values
dataframe.head()
# The last element contains the labels
labels = raw_data[:, -1]
# The other data points are the electrocadriogram data
data = raw_data[:, 0:-1]
train_data, test_data, train_labels, test_labels = train_test_split(
    data, labels, test_size=0.2, random_state=21
)
Explanation: 3番目の例：異常検出
概要
この例では、オートエンコーダーをトレーニングして、ECG5000 データセットの異常を検出します。このデータセットには、5,000 の心電図が含まれ、それぞれに 140 のデータポイントがあります。データセットの簡略化されたバージョンを使用します。各例には、0（異常なリズムに対応）または1（正常なリズムに対応）のいずれかのラベルが付けられています。ここでは異常なリズムを特定することに興味があります。
注意：これはラベル付きのデータセットであるため、教師あり学習の問題と見なせます。この例の目的は、ラベルが使用できない、より大きなデータセットに適用できる異常検出の概念を説明することです（たとえば、数千の正常なリズムがあり、異常なリズムが少数しかない場合）。
オートエンコーダーを使用すると、どのようにして異常を検出できるのでしょうか？オートエンコーダは、再構築エラーを最小限に抑えるようにトレーニングされていることを思い出してください。オートエンコーダーは通常のリズムでのみトレーニングし、それを使用してすべてのデータを再構築します。私たちの仮説は、異常なリズムはより高い再構成エラーを持つだろうということです。次に、再構成エラーが固定しきい値を超えた場合、リズムを異常として分類します。
ECG データを読み込む
使用するデータセットは、timeseriesclassification.com のデータセットに基づいています。
End of explanation
min_val = tf.reduce_min(train_data)
max_val = tf.reduce_max(train_data)
train_data = (train_data - min_val) / (max_val - min_val)
test_data = (test_data - min_val) / (max_val - min_val)
train_data = tf.cast(train_data, tf.float32)
test_data = tf.cast(test_data, tf.float32)
Explanation: データを [0,1] に正規化します。
End of explanation
train_labels = train_labels.astype(bool)
test_labels = test_labels.astype(bool)
normal_train_data = train_data[train_labels]
normal_test_data = test_data[test_labels]
anomalous_train_data = train_data[~train_labels]
anomalous_test_data = test_data[~test_labels]
Explanation: このデータセットで 1 としてラベル付けされている通常のリズムのみを使用して、オートエンコーダーをトレーニングします。正常なリズムを異常なリズムから分離します。
End of explanation
plt.grid()
plt.plot(np.arange(140), normal_train_data[0])
plt.title("A Normal ECG")
plt.show()
Explanation: 正常な ECG をプロットします。
End of explanation
plt.grid()
plt.plot(np.arange(140), anomalous_train_data[0])
plt.title("An Anomalous ECG")
plt.show()
Explanation: 異常な ECG をプロットします。
End of explanation
class AnomalyDetector(Model):
  def __init__(self):
    super(AnomalyDetector, self).__init__()
    self.encoder = tf.keras.Sequential([
      layers.Dense(32, activation="relu"),
      layers.Dense(16, activation="relu"),
      layers.Dense(8, activation="relu")])
    
    self.decoder = tf.keras.Sequential([
      layers.Dense(16, activation="relu"),
      layers.Dense(32, activation="relu"),
      layers.Dense(140, activation="sigmoid")])
    
  def call(self, x):
    encoded = self.encoder(x)
    decoded = self.decoder(encoded)
    return decoded
autoencoder = AnomalyDetector()
autoencoder.compile(optimizer='adam', loss='mae')
Explanation: モデルを構築する
End of explanation
history = autoencoder.fit(normal_train_data, normal_train_data, 
          epochs=20, 
          batch_size=512,
          validation_data=(test_data, test_data),
          shuffle=True)
plt.plot(history.history["loss"], label="Training Loss")
plt.plot(history.history["val_loss"], label="Validation Loss")
plt.legend()
Explanation: オートエンコーダは通常の ECG のみを使用してトレーニングされますが、完全なテストセットを使用して評価されることに注意してください。
End of explanation
encoded_data = autoencoder.encoder(normal_test_data).numpy()
decoded_data = autoencoder.decoder(encoded_data).numpy()
plt.plot(normal_test_data[0], 'b')
plt.plot(decoded_data[0], 'r')
plt.fill_between(np.arange(140), decoded_data[0], normal_test_data[0], color='lightcoral')
plt.legend(labels=["Input", "Reconstruction", "Error"])
plt.show()
Explanation: 再構成エラーが正常なトレーニング例からの1標準偏差より大きい場合、ECG を異常として分類します。まず、トレーニングセットからの正常な ECG、オートエンコーダーによりエンコードおよびデコードされた後の再構成、および再構成エラーをプロットします。
End of explanation
encoded_data = autoencoder.encoder(anomalous_test_data).numpy()
decoded_data = autoencoder.decoder(encoded_data).numpy()
plt.plot(anomalous_test_data[0], 'b')
plt.plot(decoded_data[0], 'r')
plt.fill_between(np.arange(140), decoded_data[0], anomalous_test_data[0], color='lightcoral')
plt.legend(labels=["Input", "Reconstruction", "Error"])
plt.show()
Explanation: 異常なテストサンプルで同様にプロットを作成します。
End of explanation
reconstructions = autoencoder.predict(normal_train_data)
train_loss = tf.keras.losses.mae(reconstructions, normal_train_data)
plt.hist(train_loss[None,:], bins=50)
plt.xlabel("Train loss")
plt.ylabel("No of examples")
plt.show()
Explanation: 異常を検出します
再構成損失が指定してしきい値より大きいかどうかを計算することにより、異常を検出します。このチュートリアルでは、トレーニングセットから正常なサンプルの平均平均誤差を計算し、再構成誤差がトレーニングセットからの1標準偏差よりも大きい場合、以降のサンプルを異常として分類します。
トレーニングセットからの通常の ECG に再構成エラーをプロットします
End of explanation
threshold = np.mean(train_loss) + np.std(train_loss)
print("Threshold: ", threshold)
Explanation: 平均より1標準偏差上のしきい値を選択します。
End of explanation
reconstructions = autoencoder.predict(anomalous_test_data)
test_loss = tf.keras.losses.mae(reconstructions, anomalous_test_data)
plt.hist(test_loss[None, :], bins=50)
plt.xlabel("Test loss")
plt.ylabel("No of examples")
plt.show()
Explanation: 注意: テストサンプルを異常として分類するしきい値を選択するために使用できるアプローチは他にもあります。適切なアプローチはデータセットによって異なります。詳細については、このチュートリアルの最後にあるリンクを参照してください。 
テストセットの異常なサンプルの再構成エラーを調べると、ほとんどの場合、再構成エラーはしきい値よりも大きいことがわかります。しきい値を変更することで、分類器の精度とリコールを調整できます。
End of explanation
def predict(model, data, threshold):
  reconstructions = model(data)
  loss = tf.keras.losses.mae(reconstructions, data)
  return tf.math.less(loss, threshold)
def print_stats(predictions, labels):
  print("Accuracy = {}".format(accuracy_score(labels, predictions)))
  print("Precision = {}".format(precision_score(labels, predictions)))
  print("Recall = {}".format(recall_score(labels, predictions)))
preds = predict(autoencoder, test_data, threshold)
print_stats(preds, test_labels)
Explanation: 再構成エラーがしきい値よりも大きい場合は、ECG を異常として分類します。
End of explanation
<END_TASK>