/
soft_3
/
Lab_CIS
Обзор
Документация
Войти
/
soft_3
/
Lab_CIS
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
CodeLab4
245 строк
9 KB
soft_3
create CodeLab4
24 окт 2025, 12:44
24 окт 2025, 12:44
33a7f0e
Код
Авторство
О чём код?
# 1. Импорты import tensorflow as tf from tensorflow.keras import layers, Model, backend as K import numpy as np import matplotlib.pyplot as plt from sklearn.manifold import TSNE print("TensorFlow version:", tf.__version__) # 2. Загрузка и предобработка данных (x_train, y_train), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data() x_train = x_train.astype('float32') / 255.0 x_test = x_test.astype('float32') / 255.0 x_train = np.expand_dims(x_train, -1) x_test = np.expand_dims(x_test, -1) print("Данные загружены и нормализованы.") # 3. Параметры модели latent_dim = 16 # Можно изменить на 2 для визуализации манифолда # 4. Слой Sampling с reparameterization trick class Sampling(layers.Layer): def call(self, inputs): z_mean, z_log_var = inputs batch = tf.shape(z_mean)[0] dim = tf.shape(z_mean)[1] epsilon = K.random_normal(shape=(batch, dim)) return z_mean + K.exp(0.5 * z_log_var) * epsilon # 5. Энкодер encoder_input = layers.Input(shape=(28, 28, 1), name='encoder_input') x = layers.Conv2D(32, kernel_size=3, strides=2, activation='relu', padding='same')(encoder_input) x = layers.Conv2D(64, kernel_size=3, strides=2, activation='relu', padding='same')(x) x = layers.Flatten()(x) x = layers.Dense(128, activation='relu')(x) z_mean = layers.Dense(latent_dim, name='z_mean')(x) z_log_var = layers.Dense(latent_dim, name='z_log_var')(x) z = Sampling()([z_mean, z_log_var]) encoder = Model(encoder_input, [z_mean, z_log_var, z], name='encoder') # 6. Декодер decoder_input = layers.Input(shape=(latent_dim,), name='decoder_input') x = layers.Dense(7 * 7 * 64, activation='relu')(decoder_input) x = layers.Reshape((7, 7, 64))(x) x = layers.Conv2DTranspose(64, kernel_size=3, strides=2, activation='relu', padding='same')(x) x = layers.Conv2DTranspose(32, kernel_size=3, strides=2, activation='relu', padding='same')(x) decoder_output = layers.Conv2DTranspose(1, kernel_size=3, activation='sigmoid', padding='same')(x) decoder = Model(decoder_input, decoder_output, name='decoder') # 7. Полная модель VAE с кастомным train_step class VAE(Model): def __init__(self, encoder, decoder, **kwargs): super(VAE, self).__init__(**kwargs) self.encoder = encoder self.decoder = decoder self.total_loss_tracker = tf.keras.metrics.Mean(name="total_loss") self.recon_loss_tracker = tf.keras.metrics.Mean(name="recon_loss") self.kl_loss_tracker = tf.keras.metrics.Mean(name="kl_loss") @property def metrics(self): return [self.total_loss_tracker, self.recon_loss_tracker, self.kl_loss_tracker] def train_step(self, data): x, y = data # y == x для VAE with tf.GradientTape() as tape: z_mean, z_log_var, z = self.encoder(x) reconstruction = self.decoder(z) # Reconstruction loss (binary crossentropy) recon_loss = tf.reduce_mean( tf.keras.losses.binary_crossentropy(y, reconstruction) ) * 28 * 28 # KL divergence kl_loss = -0.5 * tf.reduce_mean( 1 + z_log_var - tf.square(z_mean) - tf.exp(z_log_var) ) total_loss = recon_loss + kl_loss grads = tape.gradient(total_loss, self.trainable_weights) self.optimizer.apply_gradients(zip(grads, self.trainable_weights)) self.total_loss_tracker.update_state(total_loss) self.recon_loss_tracker.update_state(recon_loss) self.kl_loss_tracker.update_state(kl_loss) def call(self, inputs, training=None): # inputs — это x (изображения) z_mean, z_log_var, z = self.encoder(inputs) reconstructed = self.decoder(z) return reconstructed return { "loss": self.total_loss_tracker.result(), "recon_loss": self.recon_loss_tracker.result(), "kl_loss": self.kl_loss_tracker.result(), } # 8. Создание и компиляция модели vae = VAE(encoder, decoder) vae.compile(optimizer='adam', loss=None) # Ключевое исправление! # 9. Подготовка данных как (x, x) BATCH_SIZE = 128 EPOCHS = 20 train_dataset = tf.data.Dataset.from_tensor_slices((x_train, x_train)).batch(BATCH_SIZE) val_dataset = tf.data.Dataset.from_tensor_slices((x_test, x_test)).batch(BATCH_SIZE) # 10. Обучение модели print("Начало обучения VAE...") history = vae.fit( train_dataset, epochs=EPOCHS, validation_data=val_dataset, verbose=1 ) # 11. Визуализация обучения def plot_training_history(hist): fig, axes = plt.subplots(1, 3, figsize=(15, 4)) axes[0].plot(hist.history['loss'], label='Train') axes[0].plot(hist.history['val_loss'], label='Val') axes[0].set_title('Total Loss') axes[0].legend() axes[1].plot(hist.history['recon_loss'], label='Train') axes[1].plot(hist.history['val_recon_loss'], label='Val') axes[1].set_title('Reconstruction Loss') axes[1].legend() axes[2].plot(hist.history['kl_loss'], label='Train') axes[2].plot(hist.history['val_kl_loss'], label='Val') axes[2].set_title('KL Loss') axes[2].legend() plt.tight_layout() plt.show() plot_training_history(history) # 12. Анализ латентного пространства z_mean_test, _, _ = encoder.predict(x_test) # t-SNE проекция print("Выполняется t-SNE проекция...") tsne = TSNE(n_components=2, random_state=42, perplexity=30, n_iter=1000) z_tsne = tsne.fit_transform(z_mean_test) plt.figure(figsize=(10, 8)) scatter = plt.scatter(z_tsne[:, 0], z_tsne[:, 1], c=y_test, cmap='tab10', alpha=0.7) plt.colorbar(scatter) plt.title('t-SNE проекция латентного пространства VAE') plt.xlabel('t-SNE 1') plt.ylabel('t-SNE 2') plt.show() # 13. Генерация новых изображений def generate_and_show(n=10): z_sample = np.random.normal(size=(n, latent_dim)) generated = decoder.predict(z_sample) plt.figure(figsize=(15, 3)) for i in range(n): plt.subplot(1, n, i + 1) plt.imshow(generated[i].squeeze(), cmap='gray') plt.axis('off') plt.suptitle('Сгенерированные изображения') plt.show() generate_and_show() # 14. Интерполяция между двумя изображениями def interpolate(idx1=0, idx2=1, steps=8): z1 = z_mean_test[idx1:idx1+1] z2 = z_mean_test[idx2:idx2+1] alphas = np.linspace(0, 1, steps) interp_z = np.array([a * z2 + (1 - a) * z1 for a in alphas]).squeeze() interp_imgs = decoder.predict(interp_z) plt.figure(figsize=(12, 3)) for i in range(steps): plt.subplot(1, steps, i + 1) plt.imshow(interp_imgs[i].squeeze(), cmap='gray') plt.axis('off') plt.suptitle(f'Интерполяция между изображениями {idx1} и {idx2}') plt.show() interpolate(5, 15) # 15. Сравнение с обычным автоэнкодером print("\nОбучение обычного автоэнкодера для сравнения...") # Простой автоэнкодер ae_input = layers.Input(shape=(28, 28, 1)) x = layers.Conv2D(32, 3, strides=2, activation='relu', padding='same')(ae_input) x = layers.Conv2D(64, 3, strides=2, activation='relu', padding='same')(x) encoded = layers.Flatten()(x) x = layers.Dense(7*7*64, activation='relu')(encoded) x = layers.Reshape((7, 7, 64))(x) x = layers.Conv2DTranspose(64, 3, strides=2, activation='relu', padding='same')(x) x = layers.Conv2DTranspose(32, 3, strides=2, activation='relu', padding='same')(x) ae_output = layers.Conv2DTranspose(1, 3, activation='sigmoid', padding='same')(x) autoencoder = Model(ae_input, ae_output) autoencoder.compile(optimizer='adam', loss='binary_crossentropy') ae_history = autoencoder.fit( x_train, x_train, epochs=10, batch_size=128, verbose=0 ) # Визуальное сравнение реконструкций def compare_reconstructions(n=5): indices = np.random.choice(len(x_test), n) originals = x_test[indices] recon_vae = vae.predict((originals, originals))[0] # VAE возвращает (recon, ...) recon_ae = autoencoder.predict(originals) plt.figure(figsize=(4 * n, 6)) for i in range(n): plt.subplot(3, n, i + 1) plt.imshow(originals[i].squeeze(), cmap='gray') plt.title("Original") plt.axis('off') plt.subplot(3, n, i + 1 + n) plt.imshow(recon_vae[i].squeeze(), cmap='gray') plt.title("VAE") plt.axis('off') plt.subplot(3, n, i + 1 + 2 * n) plt.imshow(recon_ae[i].squeeze(), cmap='gray') plt.title("AE") plt.axis('off') plt.tight_layout() plt.show() compare_reconstructions()