class Polynomial3(nn.Module):
    def __init__(self):
        super().__init__()
        self.a = nn.Parameter(torch.randn(()))
        self.b = nn.Parameter(torch.randn(()))
        self.c = nn.Parameter(torch.randn(()))
        self.d = nn.Parameter(torch.randn(()))

    def forward(self, x):
        return self.a + self.b * x + self.c * x ** 2 + self.d * x ** 3

model = Polynomial3()

optimizer = optim.Adam(model.parameters(), lr=0.01)

assert isinstance(optimizer, optim.Adam), 'Optimizer should be Adam'

assert optimizer.defaults['lr'] == 0.01, 'Learning rate should be 0.01'

class Polynomial3(tf.keras.layers.Layer):
    def __init__(self):
        super().__init__()
        self.a = self.add_weight(shape=(), initializer='random_normal')
        self.b = self.add_weight(shape=(), initializer='random_normal')
        self.c = self.add_weight(shape=(), initializer='random_normal')
        self.d = self.add_weight(shape=(), initializer='random_normal')

    def call(self, x):
        return self.a + self.b * x + self.c * x ** 2 + self.d * x ** 3

model = Polynomial3()

assert isinstance(optimizer, tf.keras.optimizers.Adam), 'Optimizer should be Adam'

assert np.isclose(optimizer.learning_rate.numpy(), 0.01), 'Learning rate should be 0.01'


import torch
import torch.nn as nn
import torch.optim as optim

class AlexNet(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=0),
            nn.BatchNorm2d(96),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=3, stride=2)
        )
        self.layer2 = nn.Sequential(
            nn.Conv2d(96, 256, kernel_size=5, stride=1, padding=2),
            nn.BatchNorm2d(256),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=3, stride=2)
        )
        self.layer3 = nn.Sequential(
            nn.Conv2d(256, 384, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(384),
            nn.ReLU()
        )
        self.layer4 = nn.Sequential(
            nn.Conv2d(384, 384, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(384),
            nn.ReLU()
        )
        self.layer5 = nn.Sequential(
            nn.Conv2d(384, 256, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(256),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=3, stride=2)
        )
        self.fc = nn.Sequential(
            nn.Dropout(0.5),
            nn.Linear(9216, 4096),
            nn.ReLU()
        )
        self.fc1 = nn.Sequential(
            nn.Dropout(0.5),
            nn.Linear(4096, 4096),
            nn.ReLU()
        )
        self.fc2= nn.Sequential(
            nn.Linear(4096, num_classes)
        )
    def forward(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        out = self.layer5(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.fc1(out)
        out = self.fc2(out)
        return out

model = AlexNet(num_classes=10)

optimizer = optim.AdamW(model.parameters(), lr=0.001)

# Example usage:
# loss_fn = nn.CrossEntropyLoss()
# optimizer.zero_grad()
# output = model(x)
# loss = loss_fn(output, target)
# loss.backward()
# optimizer.step()

model = AlexNet(num_classes=10)
optimizer = optim.AdamW(model.parameters(), lr=0.001)

assert isinstance(optimizer, optim.AdamW), 'Optimizer should be AdamW'

assert optimizer.defaults['lr'] == 0.001, 'Learning rate should be 0.001'

import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import AdamW

optimizer = AdamW(learning_rate=0.001)

# Example usage:
# model.compile(optimizer=optimizer, loss='sparse_categorical_crossentropy')
# model.fit(x_train, y_train, epochs=10)

import numpy as np
model = Sequential([
    layers.Conv2D(96, kernel_size=11, strides=4, padding='valid', input_shape=(227, 227, 3)),
    layers.BatchNormalization(),
    layers.ReLU(),
    layers.MaxPooling2D(pool_size=3, strides=2),
    layers.Conv2D(256, kernel_size=5, strides=1, padding='same'),
    layers.BatchNormalization(),
    layers.ReLU(),
    layers.MaxPooling2D(pool_size=3, strides=2),
    layers.Conv2D(384, kernel_size=3, strides=1, padding='same'),
    layers.BatchNormalization(),
    layers.ReLU(),
    layers.Conv2D(384, kernel_size=3, strides=1, padding='same'),
    layers.BatchNormalization(),
    layers.ReLU(),
    layers.Conv2D(256, kernel_size=3, strides=1, padding='same'),
    layers.BatchNormalization(),
    layers.ReLU(),
    layers.MaxPooling2D(pool_size=3, strides=2),
    layers.Flatten(),
    layers.Dropout(0.5),
    layers.Dense(4096, activation='relu'),
    layers.Dropout(0.5),
    layers.Dense(4096, activation='relu'),
    layers.Dense(10, activation='softmax')
])
optimizer = AdamW(learning_rate=0.001)

assert isinstance(optimizer, tf.keras.optimizers.AdamW), 'Optimizer should be AdamW'

assert np.isclose(optimizer.learning_rate.numpy(), 0.001), 'Learning rate should be 0.001'


class LeNet5(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(1, 6, kernel_size=5, stride=1, padding=0),
            nn.BatchNorm2d(6),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        self.layer2 = nn.Sequential(
            nn.Conv2d(6, 16, kernel_size=5, stride=1, padding=0),
            nn.BatchNorm2d(16),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        self.fc = nn.Linear(400, 120)
        self.relu = nn.ReLU()
        self.fc1 = nn.Linear(120, 84)
        self.relu1 = nn.ReLU()
        self.fc2 = nn.Linear(84, num_classes)

    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = x.view(-1, 400)
        x = self.fc(x)
        x = self.relu(x)
        x = self.fc1(x)
        x = self.relu1(x)
        x = self.fc2(x)
        return x

model = LeNet5(num_classes=10)

optimizer = optim.RMSprop(model.parameters(), lr=0.001)

# Example usage:
# loss_fn = nn.CrossEntropyLoss()
# optimizer.zero_grad()
# output = model(x)
# loss = loss_fn(output, target)
# loss.backward()
# optimizer.step()

assert isinstance(optimizer, optim.RMSprop), 'Optimizer should be RMSprop'

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

optimizer = RMSprop(learning_rate=0.001)

input_shape = (32, 32, 1)
num_classes=10
model = tf.keras.Sequential([
    layers.Conv2D(6, kernel_size=(5, 5), activation='relu', input_shape=input_shape),
    layers.BatchNormalization(),
    layers.MaxPooling2D(pool_size=(2, 2)),
    layers.Conv2D(16, kernel_size=(5, 5), activation='relu'),
    layers.BatchNormalization(),
    layers.MaxPooling2D(pool_size=(2, 2)),
    layers.Flatten(),
    layers.Dense(120, activation='relu'),
    layers.Dense(84, activation='relu'),
    layers.Dense(num_classes, activation='softmax')
])
optimizer = RMSprop(learning_rate=0.001)

assert isinstance(optimizer, tf.keras.optimizers.RMSprop), 'Optimizer should be RMSprop'


import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

class LinearRegression(nn.Module):
    def __init__(self, input_size, output_size):
        super().__init__()
        self.f1 = nn.Linear(input_size, 2000)
        self.f2 = nn.Linear(2000, output_size)

    def forward(self, x):
        x = self.f1(x)
        x = F.leaky_relu(x, negative_slope=0.01)
        x = F.dropout(x, p=0.3)
        x = self.f2(x)
        return torch.sigmoid(x)

model = LinearRegression(10, 1)

optimizer = optim.RMSprop(model.parameters(), lr=0.002)

assert optimizer.defaults['lr'] == 0.002, 'Learning rate should be 0.002'

model = tf.keras.Sequential([
    layers.Dense(2000, input_dim=10, activation='leaky_relu'),
    layers.Dropout(0.3),
    layers.Dense(1, activation='sigmoid')
])

assert np.isclose(optimizer.learning_rate.numpy(), 0.002), 'Learning rate should be 0.002'


class LSTMClassifier(nn.Module):
    def __init__(self, vocab_size, output_size, embedding_dim, hidden_dim, n_layers, weights):
        super().__init__()
        self.output_size = output_size
        self.n_layers = n_layers
        self.hidden_dim = hidden_dim
        self.word_embeddings = nn.Embedding(vocab_size, embedding_dim)
        self.word_embeddings.weight = nn.Parameter(weights, requires_grad=False)
        self.dropout_1 = nn.Dropout(0.3)
        self.lstm = nn.LSTM(embedding_dim, hidden_dim, n_layers, dropout=0.3, batch_first=True)
        self.dropout_2 = nn.Dropout(0.3)
        self.label_layer = nn.Linear(hidden_dim, output_size)
        self.act = nn.Sigmoid()
    def init_hidden(self, batch_size):
        weight = next(self.parameters()).data
        return (weight.new(self.n_layers, batch_size, self.hidden_dim).zero_(), weight.new(self.n_layers, batch_size, self.hidden_dim).zero_())
    def forward(self, x, hidden):
        x = self.word_embeddings(x)
        x = self.dropout_1(x)
        lstm_out, hidden = self.lstm(x, hidden)
        lstm_out = lstm_out.contiguous().view(-1, self.hidden_dim)
        out = self.dropout_2(lstm_out)
        out = self.label_layer(out)
        out = out.view(-1, self.output_size)
        out = self.act(out)
        return out, hidden

model = LSTMClassifier(1000, 10, 300, 256, 2, torch.randn(1000, 300))

optimizer = optim.Rprop(model.parameters(), lr=0.003)

assert isinstance(optimizer, optim.Rprop), 'Optimizer should be Rprop'

assert optimizer.defaults['lr'] == 0.003, 'Learning rate should be 0.003'

class LSTMClassifier(tf.keras.Model):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, n_layers, output_size, weights):
        super().__init__()
        self.embedding = layers.Embedding(input_dim=vocab_size, output_dim=embedding_dim, weights=[weights], trainable=False)
        self.lstm = layers.LSTM(hidden_dim, return_sequences=True, dropout=0.3, recurrent_dropout=0.3)
        self.dropout = layers.Dropout(0.3)
        self.dense = layers.Dense(output_size, activation='sigmoid')
    def call(self, inputs):
        x = self.embedding(inputs)
        x = self.lstm(x)
        x = self.dropout(x)
        return self.dense(x)

model = LSTMClassifier(1000, 300, 256, 2, 10, tf.random.normal((1000, 300)))

assert np.isclose(optimizer.learning_rate.numpy(), 0.003), 'Learning rate should be 0.003'


torch.manual_seed(0)
input_tensor = torch.randn(3, 5, requires_grad=True)
target_tensor = torch.tensor([1, 0, 4])
#loss =

nll_loss = nn.NLLLoss()
loss = nll_loss(input_tensor.log_softmax(dim=1), target_tensor)

assert torch.isclose(loss, torch.tensor(expected_loss), atol=1e-4), f'Calculated loss {loss.item()} does not match expected loss {expected_loss}'

tf.random.set_seed(0)
input_tensor = tf.random.normal([3, 5], seed=0)
target_tensor = tf.constant([1, 0, 4], dtype=tf.int32)
#loss =

nll_loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
loss = nll_loss(target_tensor, input_tensor)

assert tf.experimental.numpy.isclose(loss, expected_loss, atol=1e-4), f'Calculated loss {loss.numpy()} does not match expected loss {expected_loss}'


torch.manual_seed(0)
input1 = torch.randn(3, requires_grad=True)
input2 = torch.randn(3, requires_grad=True)
target_tensor = torch.tensor([1, -1, 1])
#loss =

margin_loss = nn.MarginRankingLoss(margin=1.0)
loss = margin_loss(input1, input2, target_tensor)

tf.random.set_seed(0)
input1 = tf.random.normal([3], seed=0)
input2 = tf.random.normal([3], seed=0)
target_tensor = tf.constant([1, -1, 1], dtype=tf.float32)
#loss =

margin = 1.0
loss = tf.reduce_mean(tf.maximum(0.0, -target_tensor * (input1 - input2) + margin))


torch.manual_seed(0)
anchor = torch.randn(5, requires_grad=True)
positive = torch.randn(5, requires_grad=True)
negative = torch.randn(5, requires_grad=True)
#loss =

triplet_loss = nn.TripletMarginLoss(margin=1.0, p=2)
loss = triplet_loss(anchor, positive, negative)

tf.random.set_seed(0)
anchor = tf.random.normal([5], seed=0)
positive = tf.random.normal([5], seed=0)
negative = tf.random.normal([5], seed=0)
margin = 3.0
#loss =

positive_dist = tf.reduce_sum(tf.square(anchor - positive))
negative_dist = tf.reduce_sum(tf.square(anchor - negative))
loss = tf.maximum(positive_dist - negative_dist + margin, 0.0)


torch.manual_seed(0)
input_tensor = torch.randn(3, requires_grad=True)
target_tensor = torch.randn(3)
#loss =

kldiv_loss = nn.KLDivLoss(reduction='batchmean')
loss = kldiv_loss(torch.log_softmax(input_tensor, dim=-1), torch.softmax(target_tensor, dim=-1))

tf.random.set_seed(0)
input_tensor = tf.random.normal([3], seed=0)
target_tensor = tf.random.normal([3], seed=0)
#loss =

kldiv_loss = tf.keras.losses.KLDivergence(reduction=tf.keras.losses.Reduction.SUM_OVER_BATCH_SIZE)
loss = kldiv_loss(tf.nn.log_softmax(input_tensor), tf.nn.softmax(target_tensor))


import torch
import torch.nn.functional as F

def my_custom_loss(my_outputs, my_labels):
    # Specify the batch size
    my_batch_size = my_outputs.size()[0]
    # Calculate the log of softmax values
    my_outputs = F.log_softmax(my_outputs, dim=1)
    # Select the values that correspond to labels
    my_outputs = my_outputs[range(my_batch_size), my_labels]
    return -torch.sum(my_outputs) / my_batch_size

loss = my_custom_loss(my_outputs, my_labels)
assert torch.isclose(loss, torch.tensor(expected_loss), atol=1e-4), f'Calculated loss {loss.item()} does not match expected loss {expected_loss}'

import tensorflow as tf
from tensorflow.keras import backend as K

def my_custom_loss(my_outputs, my_labels):
    # Specify the batch size
    my_batch_size = tf.shape(my_outputs)[0]
    # Calculate the log of softmax values
    my_outputs = tf.nn.log_softmax(my_outputs, axis=1)
    # Select the values that correspond to labels
    indices = tf.stack([tf.range(my_batch_size), my_labels], axis=1)
    my_outputs = tf.gather_nd(my_outputs, indices)
    return -tf.reduce_sum(my_outputs) / tf.cast(my_batch_size, tf.float32)

loss = my_custom_loss(my_outputs, my_labels)
assert tf.experimental.numpy.isclose(loss, expected_loss, atol=1e-4), f'Calculated loss {loss.numpy()} does not match expected loss {expected_loss}'


import torch
import torch.nn as nn
import torch.nn.functional as F

class DiceLoss(nn.Module):
    def __init__(self, weight=None, size_average=True):
        super().__init__()
    def forward(self, inputs, targets, smooth=1):
        inputs = F.sigmoid(inputs)
        inputs = inputs.view(-1)
        targets = targets.view(-1)
        intersection = (inputs * targets).sum()
        dice = (2.0 * intersection + smooth) / (inputs.sum() + targets.sum() + smooth)
        return 1 - dice

loss = criterion(inputs, targets)
assert torch.isclose(loss, torch.tensor(expected_loss), atol=1e-4), f'Calculated loss {loss.item()} does not match expected loss {expected_loss}'

class DiceLoss(tf.keras.losses.Loss):
    def __init__(self, smooth=1):
        super().__init__()
        self.smooth = smooth
    def call(self, y_true, y_pred):
        y_pred = tf.nn.sigmoid(y_pred)
        y_true = tf.reshape(y_true, [-1])
        y_pred = tf.reshape(y_pred, [-1])
        intersection = tf.reduce_sum(y_true * y_pred)
        dice = (2.0 * intersection + self.smooth) / (tf.reduce_sum(y_true) + tf.reduce_sum(y_pred) + self.smooth)
        return 1 - dice

loss = criterion(targets, inputs)
assert tf.experimental.numpy.isclose(loss, expected_loss, atol=1e-4), f'Calculated loss {loss.numpy()} does not match expected loss {expected_loss}'


import torch
import torch.nn.functional as F
import numpy as np

torch.manual_seed(0)
tensor1 = torch.randn(10, requires_grad=True)
tensor2 = torch.randn(10, requires_grad=True)
# Calculate pairwise distance
# pairwise_distance =

pairwise_distance = F.pairwise_distance(tensor1.unsqueeze(0), tensor2.unsqueeze(0), p=2)

assert np.isclose(pairwise_distance.item(), expected_value, atol=1e-4), 'Pairwise distance calculation does not match expected value'

tf.random.set_seed(0)
tensor1 = tf.random.normal([10],seed=0)
tensor2 = tf.random.normal([10],seed=0)
# Calculate pairwise distance
# pairwise_distance =

pairwise_distance = tf.norm(tensor1 - tensor2, ord='euclidean')

assert tf.experimental.numpy.isclose(pairwise_distance.numpy(), expected_value, atol=1e-4), 'Pairwise distance calculation does not match expected value'


torch.manual_seed(0)
input_tensor = torch.randn(3, 5, requires_grad=True)
target_tensor = torch.rand(3, 5)
#loss =

poisson_nll_loss = nn.PoissonNLLLoss(log_input=True)
loss = poisson_nll_loss(input_tensor, target_tensor)

tf.random.set_seed(0)
input_tensor = tf.random.normal([3, 5], seed=0)
target_tensor = tf.random.uniform([3, 5], dtype=tf.float32)
#loss =

poisson_nll_loss = tf.keras.losses.Poisson()
loss = poisson_nll_loss(target_tensor, tf.math.exp(input_tensor))


torch.manual_seed(0)
input_tensor = torch.randn(3, 5, requires_grad=True)
target_tensor = torch.randn(3, 5)
var_tensor = torch.ones(3, 5)
#loss =

gaussian_nll_loss = nn.GaussianNLLLoss()
loss = gaussian_nll_loss(input_tensor, target_tensor, var_tensor)

import tensorflow as tf
import tensorflow_probability as tfp

tf.random.set_seed(0)
input_tensor = tf.random.normal([3, 5], seed=0)
target_tensor = tf.random.normal([3, 5], seed=0)
var_tensor = tf.ones([3, 5])
#loss =

gaussian_nll_loss = tf.reduce_mean(tfp.distributions.Normal(loc=input_tensor, scale=tf.sqrt(var_tensor)).log_prob(target_tensor))
loss = -gaussian_nll_loss


torch.manual_seed(0)
input_tensor = torch.sigmoid(torch.randn(3, 5, requires_grad=True))
target_tensor = torch.tensor([[1, 0, 1, 0, 1], [0, 1, 0, 1, 0], [1, 0, 1, 0, 1]], dtype=torch.float)
#loss =

bce_loss = nn.BCELoss()
loss = bce_loss(input_tensor, target_tensor)

expected_loss_1 = 0.9850
expected_loss_2 = 0.8601

assert torch.isclose(loss, torch.tensor(expected_loss_1), atol=1e-4), f'Calculated loss {loss.item()} does not match expected loss {expected_loss_1}'

input_tensor_2 = torch.sigmoid(torch.randn(3, 5, requires_grad=True))
target_tensor_2 = torch.tensor([[0, 1, 0, 1, 0], [1, 0, 1, 0, 1], [0, 1, 0, 1, 0]], dtype=torch.float)
loss_2 = bce_loss(input_tensor_2, target_tensor_2)
assert torch.isclose(loss_2, torch.tensor(expected_loss_2), atol=1e-4), f'Calculated loss {loss_2.item()} does not match expected loss {expected_loss_2}'

tf.random.set_seed(0)
input_tensor = tf.sigmoid(tf.random.normal([3, 5], seed=0))
target_tensor = tf.constant([[1, 0, 1, 0, 1], [0, 1, 0, 1, 0], [1, 0, 1, 0, 1]], dtype=tf.float32)
#loss =

bce_loss = tf.keras.losses.BinaryCrossentropy()
loss = bce_loss(target_tensor, input_tensor)

assert tf.experimental.numpy.isclose(loss, expected_loss_1, atol=1e-4), f'Calculated loss {loss.numpy()} does not match expected loss {expected_loss_1}'

input_tensor_2 = tf.sigmoid(tf.random.normal([3, 5], seed=1))
target_tensor_2 = tf.constant([[0, 1, 0, 1, 0], [1, 0, 1, 0, 1], [0, 1, 0, 1, 0]], dtype=tf.float32)
loss_2 = bce_loss(target_tensor_2, input_tensor_2)
assert tf.experimental.numpy.isclose(loss_2, expected_loss_2, atol=1e-4), f'Calculated loss {loss_2.numpy()} does not match expected loss {expected_loss_2}'


torch.manual_seed(12)
input_tensor = torch.randn(10)
# Apply dropout with rate=0.3
#output_tensor =

output_tensor = F.dropout(input_tensor, p=0.3, training=True)

nonzero_elements = output_tensor[output_tensor != 0]
assert torch.sum(output_tensor != 0).item() == expected_nonzero_count, f'Non-zero elements count {torch.sum(output_tensor != 0).item()} does not match expected {expected_nonzero_count}'

assert torch.allclose(nonzero_elements, expected_elements, atol=1e-4), f'Non-zero elements {nonzero_elements} do not match expected {expected_elements}'

tf.random.set_seed(0)
input_tensor = tf.random.normal([10])+1
# Apply dropout with rate=0.3
#output_tensor =

output_tensor = tf.nn.dropout(input_tensor, rate=0.3)

nonzero_elements = tf.gather(output_tensor, tf.where(output_tensor != 0))
assert tf.reduce_sum(tf.cast(output_tensor != 0, tf.int32)).numpy() == expected_nonzero_count, f'Non-zero elements count {tf.reduce_sum(tf.cast(output_tensor != 0, tf.int32)).numpy()} does not match expected {expected_nonzero_count}'

assert tf.reduce_all(tf.experimental.numpy.isclose(nonzero_elements, expected_elements, atol=1e-4)), f'Non-zero elements {nonzero_elements.numpy()} do not match expected {expected_elements.numpy()}'


import torch
import torch.nn as nn
import random

class DynamicNet(nn.Module):
    def __init__(self):
        super().__init__()
        # Initialize model parameters here

class DynamicNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.a = nn.Parameter(torch.randn(()))
        self.b = nn.Parameter(torch.randn(()))
        self.c = nn.Parameter(torch.randn(()))
        self.d = nn.Parameter(torch.randn(()))
        self.e = nn.Parameter(torch.randn(()))

    def forward(self, x):
        y = self.a + self.b * x + self.c * x**2 + self.d * x**3
        for exp in range(4, random.randint(4, 6)):
            y = y + self.e * x**exp
        return y

model = DynamicNet()

import torch
import random
import numpy as np
model = DynamicNet()
random.seed(0)

x = torch.tensor(2.0)
result = model(x)
assert isinstance(result, torch.Tensor), 'Model output should be a tensor'

x = torch.tensor(1.0)
result = model(x)
expected_min = model.a.item() + model.b.item() + model.c.item() + model.d.item() + model.e.item()
assert np.isclose(result.item(),expected_min), 'Polynomial output should equal to expected minimum'

x = torch.tensor([2.0, 3.0])
assert model(x).shape == torch.Size([2]), 'Output shape should match the number of input elements'

import tensorflow as tf
import numpy as np
import random

class DynamicNet(tf.keras.layers.Layer):
    def __init__(self):
        super().__init__()
        # Initialize model parameters here

class DynamicNet(tf.keras.layers.Layer):
    def __init__(self):
        super().__init__()
        self.a = self.add_weight(shape=(), initializer='random_normal')
        self.b = self.add_weight(shape=(), initializer='random_normal')
        self.c = self.add_weight(shape=(), initializer='random_normal')
        self.d = self.add_weight(shape=(), initializer='random_normal')
        self.e = self.add_weight(shape=(), initializer='random_normal')

    def call(self, x):
        y = self.a + self.b * x + self.c * x**2 + self.d * x**3
        for exp in range(4, random.randint(4, 6)):
            y = y + self.e * x**exp
        return y

model = DynamicNet()

import tensorflow as tf
import random
random.seed(0)
model = DynamicNet()

x = tf.constant(2.0)
result = model(x)
assert tf.is_tensor(result), 'Model output should be a tensor'

x = tf.constant(1.0)
result = model(x)
expected_min = model.a.numpy() + model.b.numpy() + model.c.numpy() + model.d.numpy() + model.e.numpy()
assert np.isclose(result.numpy(),expected_min), 'Polynomial output should equal to expected minimum'

x = tf.constant([2.0, 3.0])
result = model(x)
assert result.shape == (2,), 'Output shape should match the number of input elements'


import torch
import torch.nn as nn
import torch.nn.functional as F
import math

class CustomLayer(nn.Module):
    def __init__(self, in_features, out_features, custom_param):
        super().__init__()
        # Initialize weights and optional parameters

class CustomLayer(nn.Module):
    def __init__(self, in_features, out_features, custom_param):
        super().__init__()
        self.weight = nn.Parameter(torch.Tensor(out_features, in_features))
        self.bias = None  # Optionally, describe custom parameters
        self.custom_param = custom_param
        self.reset_parameters()  # Example: Initialize weights and optional parameters
    def reset_parameters(self):
        nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5))
    def forward(self, x):
        x = F.linear(x, self.weight, self.bias)
        return x

model = CustomLayer(100, 200, custom_param=0.5)

x = torch.randn(10, 100)
output = model(x)
assert output.shape == (10, 200), 'Output shape should be (10, 200)'

assert torch.is_tensor(model.weight), 'Weight should be a tensor'

assert model.custom_param == 0.5, 'Custom parameter should be 0.5'

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

class CustomLayer(layers.Layer):
    def __init__(self, in_features, out_features, custom_param):
        super(CustomLayer, self).__init__()
        # Initialize weights and optional parameters

class CustomLayer(layers.Layer):
    def __init__(self, in_features, out_features, custom_param):
        super().__init__()
        self.weight = self.add_weight(shape=(in_features, out_features), initializer=HeUniform())
        self.custom_param = custom_param
    def call(self, inputs):
        return tf.matmul(inputs, self.weight)

model = CustomLayer(100, 200, custom_param=0.5)

x = tf.random.normal([10, 100])
output = model(x)
assert output.shape == (10, 200), 'Output shape should be (10, 200)'

assert 'variable' in str(model.weight), 'Weight should be a variable'


# Set the seed for reproducibility
torch.manual_seed(42)
# Create a random tensor of dtype float64
input_tensor = torch.randn(5, dtype=torch.float64)
#long_tesnor =

expected_tensor = torch.tensor([0, 0, 0, 0, -1], dtype=torch.int64)

assert input_tensor.dtype == torch.float64, 'Input tensor should have dtype float64'

assert long_tensor.dtype == torch.int64, 'Converted tensor should have dtype int64'

assert torch.equal(long_tensor, expected_tensor), f'Converted tensor values do not match expected: {long_tensor}'

# Set the seed for reproducibility
tf.random.set_seed(42)
# Create a random tensor of dtype float64
input_tensor = tf.random.normal([5], seed = 42,dtype=tf.float64)
#long_tensor =

long_tensor = tf.cast(input_tensor, dtype=tf.int64)

expected_tensor = tf.constant([-1, 0, 0, 0, 0], dtype=tf.int64)

assert input_tensor.dtype == tf.float64, 'Input tensor should have dtype float64'

assert long_tensor.dtype == tf.int64, 'Converted tensor should have dtype int64'

assert tf.reduce_all(tf.equal(long_tensor, expected_tensor)), f'Converted tensor values do not match expected: {long_tensor.numpy()}'


# Define the model and save it to the variable 'model'.
#model = Net()

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.dropout1 = nn.Dropout2d(0.25)
        self.dropout2 = nn.Dropout2d(0.5)
        self.fc1 = nn.Linear(9216, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = F.relu(x)
        x = self.conv2(x)
        x = F.relu(x)
        x = F.max_pool2d(x, 2)
        x = self.dropout1(x)
        x = torch.flatten(x, 1)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.dropout2(x)
        x = self.fc2(x)
        output = F.log_softmax(x, dim=1)
        return output

model = Net()

assert isinstance(model.conv1, nn.Conv2d), 'First layer should be Conv2d'

assert model.conv1.out_channels == 32, 'First Conv2d layer should have 32 output channels'

assert isinstance(model.fc1, nn.Linear) and model.fc1.out_features == 128, 'First fully connected layer should have 128 output features'

input_tensor = torch.randn(1, 1, 28, 28)
output = model(input_tensor)
assert output.shape == (1, 10), 'Output tensor shape should be (1, 10)'

assert torch.allclose(output.exp().sum(dim=1), torch.tensor([1.0])), 'Output should be a valid probability distribution (sum to 1)'

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

class Net(Model):
    def __init__(self):
        super().__init__()
        self.conv1 = layers.Conv2D(32, 3, activation='relu', input_shape=(28, 28, 1))
        self.conv2 = layers.Conv2D(64, 3, activation='relu')
        self.max_pool = layers.MaxPooling2D(pool_size=(2, 2))
        self.dropout1 = layers.Dropout(0.25)
        self.flatten = layers.Flatten()
        self.fc1 = layers.Dense(128, activation='relu')
        self.dropout2 = layers.Dropout(0.5)
        self.fc2 = layers.Dense(10, activation='softmax')

    def call(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = self.max_pool(x)
        x = self.dropout1(x)
        x = self.flatten(x)
        x = self.fc1(x)
        x = self.dropout2(x)
        return self.fc2(x)

model = Net()

import numpy as np
import tensorflow as tf
model = Net()

assert isinstance(model.conv1, layers.Conv2D), 'First layer should be Conv2D'

assert model.conv1.filters == 32, 'First Conv2D layer should have 32 filters'

assert isinstance(model.fc1, layers.Dense) and model.fc1.units == 128, 'First dense layer should have 128 units'

input_tensor = tf.random.normal([1, 28, 28, 1])
output = model(input_tensor)
assert output.shape == (1, 10), 'Output tensor shape should be (1, 10)'

assert np.allclose(tf.reduce_sum(output, axis=1), tf.ones((1,))), 'Output should be a valid probability distribution (sum to 1)'


class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.dropout1 = nn.Dropout2d(0.25)
        self.dropout2 = nn.Dropout2d(0.5)
        self.fc1 = nn.Linear(9216, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = F.relu(x)
        x = self.conv2(x)
        x = F.relu(x)
        x = F.max_pool2d(x, 2)
        x = self.dropout1(x)
        x = torch.flatten(x, 1)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.dropout2(x)
        x = self.fc2(x)
        output = F.log_softmax(x, dim=1)
        return output

model = Net()

#total_params =

total_params = sum(p.numel() for p in model.parameters() if p.requires_grad)

assert total_params == 1199882, f'Expected 1199882 parameters, got {total_params}'

model = tf.keras.Sequential([
    layers.Conv2D(32, 3, activation='relu', input_shape=(28, 28, 1)),
    layers.Conv2D(64, 3, activation='relu'),
    layers.MaxPooling2D(pool_size=(2, 2)),
    layers.Dropout(0.25),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.5),
    layers.Dense(10, activation='softmax')
])


class VAE(nn.Module):
    def __init__(self):
        super().__init__()
        # Initialize the model layers here

class VAE(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 400)
        self.fc21 = nn.Linear(400, 20)
        self.fc22 = nn.Linear(400, 20)
        self.fc3 = nn.Linear(20, 400)
        self.fc4 = nn.Linear(400, 784)

    def encode(self, x):
        h1 = F.relu(self.fc1(x))
        return self.fc21(h1), self.fc22(h1)

    def reparameterize(self, mu, logvar):
        std = torch.exp(0.5*logvar)
        eps = torch.randn_like(std)
        return mu + eps*std

    def decode(self, z):
        h3 = F.relu(self.fc3(z))
        return torch.sigmoid(self.fc4(h3))

    def forward(self, x):
        mu, logvar = self.encode(x.view(-1, 784))
        z = self.reparameterize(mu, logvar)
        return self.decode(z), mu, logvar

model = VAE()

input_tensor = torch.randn(1, 784)
output, mu, logvar = model(input_tensor)
assert output.shape == (1, 784), 'Output shape should be (1, 784)'

assert mu.shape == logvar.shape == torch.Size([1, 20]), 'Mu and logvar shapes should be (1, 20)'

z = model.reparameterize(mu, logvar)
assert z.shape == torch.Size([1, 20]), 'Latent variable z should have shape (1, 20)'

# Define the VAE model using TensorFlow/Keras

class VAE(Model):
    def __init__(self):
        super().__init__()
        self.fc1 = layers.Dense(400, activation='relu')
        self.fc21 = layers.Dense(20)
        self.fc22 = layers.Dense(20)
        self.fc3 = layers.Dense(400, activation='relu')
        self.fc4 = layers.Dense(784, activation='sigmoid')

    def encode(self, x):
        h1 = self.fc1(x)
        return self.fc21(h1), self.fc22(h1)

    def reparameterize(self, mu, logvar):
        std = tf.exp(0.5 * logvar)
        eps = tf.random.normal(std.shape)
        return mu + eps * std

    def decode(self, z):
        h3 = self.fc3(z)
        return self.fc4(h3)

    def call(self, x):
        mu, logvar = self.encode(tf.reshape(x, [-1, 784]))
        z = self.reparameterize(mu, logvar)
        return self.decode(z), mu, logvar

model = VAE()

import numpy as np
import tensorflow as tf
model = VAE()

input_tensor = tf.random.normal([1, 784])
output, mu, logvar = model(input_tensor)
assert output.shape == (1, 784), 'Output shape should be (1, 784)'

assert mu.shape == logvar.shape == (1, 20), 'Mu and logvar shapes should be (1, 20)'

z = model.reparameterize(mu, logvar)
assert z.shape == (1, 20), 'Latent variable z should have shape (1, 20)'


class Generator(nn.Module):
    def __init__(self, ngpu):
        super().__init__()
        nz = 100
        ngf = 64
        nc = 3
        self.ngpu = ngpu
        self.main = nn.Sequential(
            nn.ConvTranspose2d(nz, ngf * 8, 4, 1, 0, bias=False),
            nn.BatchNorm2d(ngf * 8),
            nn.ReLU(True),
            nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf * 4),
            nn.ReLU(True),
            nn.ConvTranspose2d(ngf * 4, ngf * 2, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf * 2),
            nn.ReLU(True),
            nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf),
            nn.ReLU(True),
            nn.ConvTranspose2d(ngf, nc, 4, 2, 1, bias=False),
            nn.Tanh()
        )

    def forward(self, input):
        if input.is_cuda and self.ngpu > 1:
            output = nn.parallel.data_parallel(self.main, input, range(self.ngpu))
        else:
            output = self.main(input)
        return output

model = Generator(ngpu=1)

nz = 100
ngf = 64
nc = 3
model = Generator(ngpu=1)

input_tensor = torch.randn(1, nz, 1, 1)
output = model(input_tensor)
assert output.shape == (1, nc, 64, 64), 'Output shape should be (1, nc, 64, 64)'

assert isinstance(model.main[0], nn.ConvTranspose2d), 'First layer should be ConvTranspose2d'

assert isinstance(model.main[-1], nn.Tanh), 'Last layer should be Tanh activation'

class Generator(Model):
    def __init__(self):
        super().__init__()
        nz = 100
        ngf = 64
        nc = 3
        self.main = tf.keras.Sequential([
            layers.Conv2DTranspose(ngf * 8, (4, 4), strides=(1, 1), padding='valid', use_bias=False),
            layers.BatchNormalization(),
            layers.ReLU(),
            layers.Conv2DTranspose(ngf * 4, (4, 4), strides=(2, 2), padding='same', use_bias=False),
            layers.BatchNormalization(),
            layers.ReLU(),
            layers.Conv2DTranspose(ngf * 2, (4, 4), strides=(2, 2), padding='same', use_bias=False),
            layers.BatchNormalization(),
            layers.ReLU(),
            layers.Conv2DTranspose(ngf, (4, 4), strides=(2, 2), padding='same', use_bias=False),
            layers.BatchNormalization(),
            layers.ReLU(),
            layers.Conv2DTranspose(nc, (4, 4), strides=(2, 2), padding='same', use_bias=False),
            layers.Activation('tanh')
        ])

    def call(self, input):
        return self.main(input)

model = Generator()

nz = 100
ngf = 64
nc = 3
model = Generator()

input_tensor = tf.random.normal([1, 1, 1, nz])
output = model(input_tensor)
assert output.shape == (1, 64, 64, nc), 'Output shape should be (1, 64, 64, nc)'

assert isinstance(model.main.layers[0], layers.Conv2DTranspose), 'First layer should be Conv2DTranspose'

assert isinstance(model.main.layers[-1], layers.Activation) and model.main.layers[-1].activation == tf.keras.activations.tanh, 'Last layer should be Tanh activation'


# Define the BoWClassifier model
#model = BoWClassifier(num_labels, vocab_size)

class BoWClassifier(nn.Module):

    def __init__(self, num_labels, vocab_size):
        super().__init__()
        self.linear = nn.Linear(vocab_size, num_labels)

    def forward(self, bow_vec):
        return F.log_softmax(self.linear(bow_vec), dim=1)

# Define a BoWClassifier with 2 labels and a vocabulary size of 1000
model = BoWClassifier(num_labels=2, vocab_size=1000)

model = BoWClassifier(num_labels=2, vocab_size=1000)
input_tensor = torch.zeros(1, 1000)
input_tensor[0, 100] = 1
input_tensor[0, 200] = 1

output = model(input_tensor)
assert output.shape == (1, 2), 'Output should be of shape (1, 2)'

assert isinstance(model.linear, nn.Linear), 'The model should contain a Linear layer'

assert torch.allclose(output.exp().sum(), torch.tensor(1.0)), 'The output probabilities should sum to 1'

class BoWClassifier(Model):

    def __init__(self, num_labels, vocab_size):
        super().__init__()
        self.linear = layers.Dense(num_labels)

    def call(self, bow_vec):
        return tf.nn.log_softmax(self.linear(bow_vec), axis=1)

# Define a BoWClassifier with 2 labels and a vocabulary size of 1000
model = BoWClassifier(num_labels=2, vocab_size=1000)

model = BoWClassifier(num_labels=2, vocab_size=1000)
input_tensor = tf.zeros([1, 1000])
input_tensor = tf.tensor_scatter_nd_update(input_tensor, [[0, 100], [0, 200]], [1.0, 1.0])

assert isinstance(model.linear, layers.Dense), 'The model should contain a Dense layer'

assert tf.reduce_all(tf.exp(output) <= 1.0), 'The output values should represent valid probabilities'


# Define the LSTMTagger model
#model = LSTMTagger(embedding_dim, hidden_dim, vocab_size, tagset_size)

class LSTMTagger(nn.Module):

    def __init__(self, embedding_dim, hidden_dim, vocab_size, tagset_size):
        super().__init__()
        self.hidden_dim = hidden_dim
        self.word_embeddings = nn.Embedding(vocab_size, embedding_dim)
        self.lstm = nn.LSTM(embedding_dim, hidden_dim)
        self.hidden2tag = nn.Linear(hidden_dim, tagset_size)

    def forward(self, sentence):
        embeds = self.word_embeddings(sentence)
        lstm_out, _ = self.lstm(embeds.view(len(sentence), 1, -1))
        tag_space = self.hidden2tag(lstm_out.view(len(sentence), -1))
        tag_scores = F.log_softmax(tag_space, dim=1)
        return tag_scores

# Define the LSTMTagger with appropriate dimensions
model = LSTMTagger(embedding_dim=6, hidden_dim=6, vocab_size=10, tagset_size=3)

model = LSTMTagger(embedding_dim=6, hidden_dim=6, vocab_size=10, tagset_size=3)
sentence = torch.tensor([1, 2, 3, 4], dtype=torch.long)

tag_scores = model(sentence)
assert tag_scores.shape == (4, 3), 'Tag scores shape should be (sentence_length, tagset_size)'

assert isinstance(model.lstm, nn.LSTM), 'Model should contain an LSTM layer'

assert isinstance(model.hidden2tag, nn.Linear), 'Model should contain a Linear layer mapping hidden states to tag scores'

assert torch.allclose(tag_scores.exp().sum(dim=1), torch.tensor(1.0)), 'Each tag score row should sum to 1 (valid probability distribution)'

class LSTMTagger(Model):

    def __init__(self, embedding_dim, hidden_dim, vocab_size, tagset_size):
        super().__init__()
        self.embedding = layers.Embedding(vocab_size, embedding_dim)
        self.lstm = layers.LSTM(hidden_dim, return_sequences=True)
        self.hidden2tag = layers.Dense(tagset_size)

    def call(self, sentence):
        # Add batch dimension if not already present
        if len(sentence.shape) == 1:
            sentence = tf.expand_dims(sentence, axis=0)
        embeds = self.embedding(sentence)
        lstm_out = self.lstm(embeds)
        tag_space = self.hidden2tag(lstm_out)
        tag_scores = tf.nn.log_softmax(tag_space, axis=-1)
        return tag_scores

# Define the LSTMTagger with appropriate dimensions
model = LSTMTagger(embedding_dim=6, hidden_dim=6, vocab_size=10, tagset_size=3)

sentence = tf.constant([1, 2, 3, 4], dtype=tf.int32)
model = LSTMTagger(embedding_dim=6, hidden_dim=6, vocab_size=10, tagset_size=3)

tag_scores = model(sentence)
assert tag_scores.shape == (1, 4, 3), 'Tag scores shape should be (batch_size, sequence_length, tagset_size)'

sentence_batch = tf.constant([[1, 2, 3, 4], [1, 2, 3, 0]], dtype=tf.int32)
tag_scores_batch = model(sentence_batch)
assert tag_scores_batch.shape == (2, 4, 3), 'Tag scores shape should be (batch_size, sequence_length, tagset_size)'

assert isinstance(model.lstm, layers.LSTM), 'Model should contain an LSTM layer'

assert isinstance(model.hidden2tag, layers.Dense), 'Model should contain a Dense layer mapping hidden states to tag scores'

assert tf.reduce_all(tf.exp(tag_scores) <= 1.0), 'Tag scores should represent valid probabilities'


class EncoderRNN(nn.Module):
    def __init__(self, input_size, hidden_size, dropout_p=0.1):
        super().__init__()
        self.hidden_size = hidden_size
        self.embedding = nn.Embedding(input_size, hidden_size)
        self.gru = nn.GRU(hidden_size, hidden_size, batch_first=True)
        self.dropout = nn.Dropout(dropout_p)

    def forward(self, input):
        embedded = self.dropout(self.embedding(input))
        output, hidden = self.gru(embedded)
        return output, hidden

# Initialize the EncoderRNN
model = EncoderRNN(input_size=10, hidden_size=20, dropout_p=0.1)

class EncoderRNN(nn.Module):
    def __init__(self, input_size, hidden_size, dropout_p=0.1):
        super().__init__()
        self.hidden_size = hidden_size
        self.embedding = nn.Embedding(input_size, hidden_size)
        self.gru = nn.GRU(hidden_size, hidden_size, batch_first=True)
        self.dropout = nn.Dropout(dropout_p)

    def forward(self, input):
        embedded = self.dropout(self.embedding(input))
        output, hidden = self.gru(embedded)
        return output, hidden

model = EncoderRNN(input_size=10, hidden_size=20, dropout_p=0.1)

model = EncoderRNN(input_size=10, hidden_size=20)
sentence = torch.tensor([[1, 2, 3, 4]])

output, hidden = model(sentence)
assert output.shape == (1, 4, 20), 'Output shape should be (batch_size, sequence_length, hidden_size)'

assert hidden.shape == (1, 1, 20), 'Hidden shape should be (num_layers, batch_size, hidden_size)'

assert isinstance(model.embedding, nn.Embedding), 'Embedding layer should be of type nn.Embedding'

assert isinstance(model.gru, nn.GRU), 'RNN layer should be of type nn.GRU'

assert isinstance(model.dropout, nn.Dropout), 'Dropout layer should be of type nn.Dropout'

class EncoderRNN(Model):
    def __init__(self, input_size, hidden_size, dropout_p=0.1):
        super().__init__()
        self.embedding = layers.Embedding(input_size, hidden_size)
        self.gru = layers.GRU(hidden_size, return_sequences=True, return_state=True)
        self.dropout = layers.Dropout(dropout_p)

    def call(self, input):
        embedded = self.dropout(self.embedding(input))
        output, hidden = self.gru(embedded)
        return output, hidden

model = EncoderRNN(input_size=10, hidden_size=20, dropout_p=0.1)

sentence = tf.constant([[1, 2, 3, 4]])
model = EncoderRNN(input_size=10, hidden_size=20, dropout_p=0.1)

assert hidden.shape == (1, 20), 'Hidden shape should be (batch_size, hidden_size)'

assert isinstance(model.embedding, layers.Embedding), 'Embedding layer should be of type layers.Embedding'

assert isinstance(model.gru, layers.GRU), 'RNN layer should be of type layers.GRU'

assert isinstance(model.dropout, layers.Dropout), 'Dropout layer should be of type layers.Dropout'


class DecoderRNN(nn.Module):
    def __init__(self, hidden_size, output_size):
        super().__init__()
        self.embedding = nn.Embedding(output_size, hidden_size)
        self.gru = nn.GRU(hidden_size, hidden_size, batch_first=True)
        self.out = nn.Linear(hidden_size, output_size)
        self.SOS_token = 0
        self.MAX_LENGTH = 5

    def forward(self, encoder_outputs, encoder_hidden, target_tensor=None):
        pass

class DecoderRNN(nn.Module):
    def __init__(self, hidden_size, output_size):
        super().__init__()
        self.embedding = nn.Embedding(output_size, hidden_size)
        self.gru = nn.GRU(hidden_size, hidden_size, batch_first=True)
        self.out = nn.Linear(hidden_size, output_size)
        self.SOS_token = 0
        self.MAX_LENGTH = 5

    def forward(self, encoder_outputs, encoder_hidden, target_tensor=None):
        batch_size = encoder_outputs.size(0)
        decoder_input = torch.empty(batch_size, 1, dtype=torch.long).fill_(self.SOS_token)
        decoder_hidden = encoder_hidden
        decoder_outputs = []

        for i in range(self.MAX_LENGTH):
            decoder_output, decoder_hidden = self.forward_step(decoder_input, decoder_hidden)
            decoder_outputs.append(decoder_output)
            if target_tensor is not None:
                decoder_input = target_tensor[:, i].unsqueeze(1)  # Teacher forcing
            else:
                _, topi = decoder_output.topk(1)
                decoder_input = topi.squeeze(-1).detach()

        decoder_outputs = torch.cat(decoder_outputs, dim=1)
        decoder_outputs = F.log_softmax(decoder_outputs, dim=-1)
        return decoder_outputs, decoder_hidden, None

    def forward_step(self, input, hidden):
        output = self.embedding(input)
        output = F.relu(output)
        output, hidden = self.gru(output, hidden)
        output = self.out(output)
        return output, hidden

model = DecoderRNN(hidden_size=20, output_size=10)

hidden_size = 20
output_size = 10
decoder = DecoderRNN(hidden_size, output_size)
encoder_hidden = torch.zeros(1, 1, hidden_size)
encoder_outputs = torch.zeros(1, decoder.MAX_LENGTH, hidden_size)
target_tensor = torch.tensor([[1, 2, 3, 4, 5]])

decoder_outputs, decoder_hidden, _ = decoder(encoder_outputs, encoder_hidden, target_tensor)
assert decoder_outputs.shape == (1, decoder.MAX_LENGTH, output_size), 'Decoder output shape should be (batch_size, MAX_LENGTH, output_size)'

assert decoder_hidden.shape == (1, 1, hidden_size), 'Decoder hidden state shape should match (num_layers, batch_size, hidden_size)'

assert isinstance(decoder.embedding, nn.Embedding), 'Embedding layer should be of type nn.Embedding'

assert isinstance(decoder.gru, nn.GRU), 'GRU layer should be of type nn.GRU'

assert isinstance(decoder.out, nn.Linear), 'Final output layer should be a Linear layer'

class DecoderRNN(Model):
    def __init__(self, hidden_size, output_size):
        super().__init__()
        self.embedding = layers.Embedding(output_size, hidden_size)
        self.gru = layers.GRU(hidden_size, return_sequences=True, return_state=True)
        self.out = layers.Dense(output_size)
        self.SOS_token = 0
        self.MAX_LENGTH = 5

    def call(self, encoder_outputs, encoder_hidden, target_tensor=None):
        pass

class DecoderRNN(Model):
    def __init__(self, hidden_size, output_size):
        super().__init__()
        self.embedding = layers.Embedding(output_size, hidden_size)
        self.gru = layers.GRU(hidden_size, return_sequences=True, return_state=True)
        self.out = layers.Dense(output_size)
        self.SOS_token = 0
        self.MAX_LENGTH = 5

    def call(self, encoder_outputs, encoder_hidden, target_tensor=None):
        batch_size = tf.shape(encoder_outputs)[0]
        decoder_input = tf.fill([batch_size, 1], self.SOS_token)
        decoder_hidden = encoder_hidden
        decoder_outputs = []

        for i in range(self.MAX_LENGTH):
            decoder_output, decoder_hidden = self.forward_step(decoder_input, decoder_hidden)
            decoder_outputs.append(decoder_output)
            if target_tensor is not None:
                decoder_input = tf.expand_dims(target_tensor[:, i], axis=1)
            else:
                decoder_input = tf.argmax(decoder_output, axis=-1)

        decoder_outputs = tf.concat(decoder_outputs, axis=1)
        decoder_outputs = tf.nn.log_softmax(decoder_outputs, axis=-1)
        return decoder_outputs, decoder_hidden, None

    def forward_step(self, input, hidden):
        output = self.embedding(input)
        output = tf.nn.relu(output)
        output, hidden = self.gru(output, initial_state=hidden)
        output = self.out(output)
        return output, hidden

model = DecoderRNN(hidden_size=20, output_size=10)

hidden_size = 20
output_size = 10
encoder_hidden = tf.zeros([1, hidden_size])
encoder_outputs = tf.zeros([1, 5, hidden_size])
target_tensor = tf.constant([[1, 2, 3, 4, 5]])

decoder_outputs, decoder_hidden, _ = model(encoder_outputs, encoder_hidden, target_tensor)
assert decoder_outputs.shape == (1, model.MAX_LENGTH, output_size), 'Decoder output shape should be (batch_size, MAX_LENGTH, output_size)'

assert decoder_hidden.shape == (1, hidden_size), 'Decoder hidden state shape should match (batch_size, hidden_size)'

assert isinstance(model.gru, layers.GRU), 'GRU layer should be of type layers.GRU'

assert isinstance(model.out, layers.Dense), 'Final output layer should be a Dense layer'


class BahdanauAttention(nn.Module):
    def __init__(self, hidden_size):
        super().__init__()
        self.Wa = nn.Linear(hidden_size, hidden_size)
        self.Ua = nn.Linear(hidden_size, hidden_size)
        self.Va = nn.Linear(hidden_size, 1)

    def forward(self, query, keys):
        pass
        #scores=

class BahdanauAttention(nn.Module):
    def __init__(self, hidden_size):
        super().__init__()
        self.Wa = nn.Linear(hidden_size, hidden_size)
        self.Ua = nn.Linear(hidden_size, hidden_size)
        self.Va = nn.Linear(hidden_size, 1)

    def forward(self, query, keys):
        scores = self.Va(torch.tanh(self.Wa(query) + self.Ua(keys)))
        scores = scores.squeeze(2).unsqueeze(1)
        weights = F.softmax(scores, dim=-1)
        context = torch.bmm(weights, keys)
        return context, weights

hidden_size = 128
query = torch.randn(16, 1, hidden_size)
keys = torch.randn(16, 10, hidden_size)
model = BahdanauAttention(hidden_size)

context, weights = model(query, keys)
assert context.shape == (16, 1, hidden_size), f'Context shape mismatch: {context.shape}'

assert weights.shape == (16, 1, 10), f'Attention weights shape mismatch: {weights.shape}'

assert isinstance(model.Wa, nn.Linear), 'Wa should be an instance of nn.Linear'

assert isinstance(model.Ua, nn.Linear), 'Ua should be an instance of nn.Linear'

assert isinstance(model.Va, nn.Linear), 'Va should be an instance of nn.Linear'

class BahdanauAttention(tf.keras.layers.Layer):
    def __init__(self, hidden_size):
        super().__init__()
        self.Wa = layers.Dense(hidden_size)
        self.Ua = layers.Dense(hidden_size)
        self.Va = layers.Dense(1)

    def call(self, query, keys):

        pass
        #scores=

class BahdanauAttention(tf.keras.layers.Layer):
    def __init__(self, hidden_size):
        super().__init__()
        self.Wa = layers.Dense(hidden_size)
        self.Ua = layers.Dense(hidden_size)
        self.Va = layers.Dense(1)

    def call(self, query, keys):
        scores = self.Va(tf.nn.tanh(self.Wa(query) + self.Ua(keys)))
        scores = tf.squeeze(scores, axis=-1)
        weights = tf.nn.softmax(scores, axis=-1)
        weights = tf.expand_dims(weights, axis=1)
        context = tf.matmul(weights, keys)
        return context, weights

hidden_size = 128
query = tf.random.normal([16, 1, hidden_size])
keys = tf.random.normal([16, 10, hidden_size])
model = BahdanauAttention(hidden_size)

assert isinstance(model.Wa, layers.Dense), 'Wa should be an instance of layers.Dense'

assert isinstance(model.Ua, layers.Dense), 'Ua should be an instance of layers.Dense'

assert isinstance(model.Va, layers.Dense), 'Va should be an instance of layers.Dense'


class SimpleMLP(nn.Module):
    def __init__(self):
        super().__init__()
        # Initialize layers here

class SimpleMLP(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 128)
        self.fc2 = nn.Linear(128, 128)
        self.fc3 = nn.Linear(128, 10)

    def forward(self, x):
        x = x.flatten(1)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        x = F.relu(x)
        x = self.fc3(x)
        return x

model = SimpleMLP()
input_tensor = torch.randn(32, 1, 28, 28)

output = model(input_tensor)
assert output.shape == (32, 10), f'Expected output shape (32, 10), got {output.shape}'

assert isinstance(model.fc1, nn.Linear), 'First layer should be Linear'

assert isinstance(model.fc2, nn.Linear), 'Second layer should be Linear'

assert isinstance(model.fc3, nn.Linear), 'Third layer should be Linear'

class SimpleMLP(tf.keras.Model):
    def __init__(self):
        super().__init__()
        # Initialize layers here

class SimpleMLP(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.fc1 = layers.Dense(128, activation='relu')
        self.fc2 = layers.Dense(128, activation='relu')
        self.fc3 = layers.Dense(10)

    def call(self, x):
        x = tf.reshape(x, [tf.shape(x)[0], -1])
        x = self.fc1(x)
        x = self.fc2(x)
        return self.fc3(x)

model = SimpleMLP()
input_tensor = tf.random.normal([32, 28, 28, 1])

assert isinstance(model.fc1, layers.Dense), 'First layer should be Dense'

assert isinstance(model.fc2, layers.Dense), 'Second layer should be Dense'

assert isinstance(model.fc3, layers.Dense), 'Third layer should be Dense'


class TextClassificationModel(nn.Module):
    def __init__(self, vocab_size, embed_dim, num_class):
        super().__init__()
        # Initialize layers here

class TextClassificationModel(nn.Module):
    def __init__(self, vocab_size, embed_dim, num_class):
        super().__init__()
        self.embedding = nn.EmbeddingBag(vocab_size, embed_dim, sparse=False)
        self.fc = nn.Linear(embed_dim, num_class)
        self.init_weights()

    def init_weights(self):
        initrange = 0.5
        self.embedding.weight.data.uniform_(-initrange, initrange)
        self.fc.weight.data.uniform_(-initrange, initrange)
        self.fc.bias.data.zero_()

    def forward(self, text, offsets):
        embedded = self.embedding(text, offsets)
        return self.fc(embedded)

vocab_size = 10000
embed_dim = 64
num_class = 5
model = TextClassificationModel(vocab_size, embed_dim, num_class)
text = torch.randint(0, vocab_size, (32,))
offsets = torch.tensor([0])

output = model(text, offsets)
assert output.shape == (1, num_class), f'Expected output shape (1, {num_class}), got {output.shape}'

assert isinstance(model.embedding, nn.EmbeddingBag), 'First layer should be EmbeddingBag'

assert isinstance(model.fc, nn.Linear), 'Second layer should be Linear'

class TextClassificationModel(tf.keras.Model):
    def __init__(self, vocab_size, embed_dim, num_class):
        super().__init__()
        # Initialize layers here

class TextClassificationModel(tf.keras.Model):
    def __init__(self, vocab_size, embed_dim, num_class):
        super().__init__()
        self.embedding = layers.Embedding(input_dim=vocab_size, output_dim=embed_dim)
        self.fc = layers.Dense(num_class)

    def call(self, text, offsets):
        x = self.embedding(text)
        x = tf.reduce_mean(x, axis=1)
        return self.fc(x)

vocab_size = 10000
embed_dim = 64
num_class = 5
model = TextClassificationModel(vocab_size, embed_dim, num_class)
text = tf.random.uniform((32, 1), maxval=vocab_size, dtype=tf.int32)
offsets = tf.constant([0])

output = model(text, offsets)
assert output.shape == (32, num_class), f'Expected output shape (32, {num_class}), got {output.shape}'

assert isinstance(model.embedding, layers.Embedding), 'First layer should be Embedding'

assert isinstance(model.fc, layers.Dense), 'Second layer should be Dense'


import torch
import torch.nn as nn
import torch.nn.init as init
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self, upscale_factor):
        super().__init__()
        # Initialize layers here

class Net(nn.Module):
    def __init__(self, upscale_factor):
        super().__init__()
        self.relu = nn.ReLU()
        self.conv1 = nn.Conv2d(1, 64, (5, 5), (1, 1), (2, 2))
        self.conv2 = nn.Conv2d(64, 64, (3, 3), (1, 1), (1, 1))
        self.conv3 = nn.Conv2d(64, 32, (3, 3), (1, 1), (1, 1))
        self.conv4 = nn.Conv2d(32, upscale_factor ** 2, (3, 3), (1, 1), (1, 1))
        self.pixel_shuffle = nn.PixelShuffle(upscale_factor)
        self._initialize_weights()

    def forward(self, x):
        x = self.relu(self.conv1(x))
        x = self.relu(self.conv2(x))
        x = self.relu(self.conv3(x))
        x = self.pixel_shuffle(self.conv4(x))
        return x

    def _initialize_weights(self):
        init.orthogonal_(self.conv1.weight, init.calculate_gain('relu'))
        init.orthogonal_(self.conv2.weight, init.calculate_gain('relu'))
        init.orthogonal_(self.conv3.weight, init.calculate_gain('relu'))
        init.orthogonal_(self.conv4.weight)

model = Net(upscale_factor=2)

model = Net(upscale_factor=2)
input_tensor = torch.randn(1, 1, 16, 16)

output = model(input_tensor)
assert output.shape == (1, 1, 32, 32), f'Expected output shape (1, 1, 32, 32), got {output.shape}'

assert isinstance(model.conv1, nn.Conv2d), 'First layer should be Conv2d'

assert isinstance(model.pixel_shuffle, nn.PixelShuffle), 'PixelShuffle layer should be PixelShuffle'

assert model.conv1.out_channels == 64, 'First convolution should have 64 output channels'

class Net(Model):
    def __init__(self, upscale_factor):
        super().__init__()
        # Initialize layers here

class Net(Model):
    def __init__(self, upscale_factor):
        super().__init__()
        self.conv1 = layers.Conv2D(64, (5, 5), padding='same', activation='relu')
        self.conv2 = layers.Conv2D(64, (3, 3), padding='same', activation='relu')
        self.conv3 = layers.Conv2D(32, (3, 3), padding='same', activation='relu')
        self.conv4 = layers.Conv2D(upscale_factor ** 2, (3, 3), padding='same')
        self.upscale_factor = upscale_factor

    def call(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = self.conv3(x)
        x = self.conv4(x)
        x = tf.nn.depth_to_space(x, self.upscale_factor)
        return x

model = Net(upscale_factor=2)

model = Net(upscale_factor=2)
input_tensor = tf.random.normal([1, 16, 16, 1])

output = model(input_tensor)
assert output.shape == (1, 32, 32, 1), f'Expected output shape (1, 32, 32, 1), got {output.shape}'

assert isinstance(model.conv1, layers.Conv2D), 'First layer should be Conv2D'

assert model.conv1.filters == 64, 'First convolution should have 64 filters'


class Net(nn.Module):
    def __init__(self):
        super().__init__()
        # Initialize layers here

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.rnn = nn.LSTM(input_size=28, hidden_size=64, batch_first=True)
        self.batchnorm = nn.BatchNorm1d(64)
        self.dropout1 = nn.Dropout2d(0.25)
        self.dropout2 = nn.Dropout2d(0.5)
        self.fc1 = nn.Linear(64, 32)
        self.fc2 = nn.Linear(32, 10)

    def forward(self, input):
        input = input.reshape(-1, 28, 28)
        output, hidden = self.rnn(input)
        output = output[:, -1, :]
        output = self.batchnorm(output)
        output = self.dropout1(output)
        output = self.fc1(output)
        output = F.relu(output)
        output = self.dropout2(output)
        output = self.fc2(output)
        output = F.log_softmax(output, dim=1)
        return output

model = Net()

model = Net()
input_tensor = torch.randn(32, 1, 28, 28)

output = model(input_tensor)
assert output.shape == (32, 10), f'Expected output shape (32, 10), got {output.shape}'

assert isinstance(model.rnn, nn.LSTM), 'First layer should be LSTM'

assert isinstance(model.fc1, nn.Linear) and model.fc1.out_features == 32, 'First fully connected layer should have 32 output features'

class Net(Model):
    def __init__(self):
        super().__init__()
        # Initialize layers here

class Net(Model):
    def __init__(self):
        super().__init__()
        self.lstm = layers.LSTM(64, input_shape=(28, 28), return_sequences=False)
        self.batchnorm = layers.BatchNormalization()
        self.dropout1 = layers.Dropout(0.25)
        self.fc1 = layers.Dense(32, activation='relu')
        self.dropout2 = layers.Dropout(0.5)
        self.fc2 = layers.Dense(10, activation='softmax')

    def call(self, x):
        x = tf.reshape(x, [-1, 28, 28])
        x = self.lstm(x)
        x = self.batchnorm(x)
        x = self.dropout1(x)
        x = self.fc1(x)
        x = self.dropout2(x)
        return self.fc2(x)

model = Net()

model = Net()
input_tensor = tf.random.normal([32, 1, 28, 28])

assert isinstance(model.lstm, layers.LSTM), 'First layer should be LSTM'

assert isinstance(model.fc1, layers.Dense) and model.fc1.units == 32, 'First fully connected layer should have 32 units'


class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
        self.conv2_drop = nn.Dropout2d()
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)

    def forward(self, x):
        x = F.relu(F.max_pool2d(self.conv1(x), 2))
        x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
        x = x.view(-1, 320)
        x = F.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)

model = Net()

assert isinstance(model.fc1, nn.Linear) and model.fc1.out_features == 50, 'First fully connected layer should have 50 output features'

class Net(Model):
    def __init__(self):
        super().__init__()
        self.conv1 = layers.Conv2D(10, kernel_size=5, activation='relu', input_shape=(28, 28, 1))
        self.conv2 = layers.Conv2D(20, kernel_size=5, activation='relu')
        self.max_pool = layers.MaxPooling2D(pool_size=(2, 2))
        self.dropout = layers.Dropout(0.5)
        self.flatten = layers.Flatten()
        self.fc1 = layers.Dense(50, activation='relu')
        self.fc2 = layers.Dense(10, activation='softmax')

    def call(self, x):
        x = self.conv1(x)
        x = self.max_pool(x)
        x = self.conv2(x)
        x = self.max_pool(x)
        x = self.dropout(x)
        x = self.flatten(x)
        x = self.fc1(x)
        return self.fc2(x)

model = Net()

model = Net()
input_tensor = tf.random.normal([32, 28, 28, 1])

assert isinstance(model.fc1, layers.Dense) and model.fc1.units == 50, 'First fully connected layer should have 50 units'


# Define the loss function
#def loss_function(recon_x, x, mu, logvar):

def loss_function(recon_x, x, mu, logvar):
    BCE = F.binary_cross_entropy(recon_x, x.view(-1, 784), reduction='sum')
    KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
    return BCE + KLD

recon_x = torch.sigmoid(torch.randn(64, 784))
x = torch.sigmoid(torch.randn(64, 28, 28))
mu = torch.randn(64, 20)
logvar = torch.randn(64, 20)

loss = loss_function(recon_x, x, mu, logvar)
assert loss.item() > 0, 'Loss should be positive'

assert loss_function(recon_x, x, mu, logvar).dtype == torch.float32, 'Loss should be a floating-point tensor'

assert torch.isfinite(loss_function(recon_x, x, mu, logvar)), 'Loss should be finite and not NaN/Inf'

x_zeros = torch.zeros_like(x)
assert loss_function(recon_x, x_zeros, mu, logvar).item() > 0, 'Loss with zero target should be positive'

recon_zeros = torch.zeros_like(recon_x)
assert loss_function(recon_zeros, x, mu, logvar).item() > 0, 'Loss with zero reconstruction should be positive'

def loss_function(recon_x, x, mu, logvar):
    BCE = tf.keras.losses.binary_crossentropy(x, recon_x)
    BCE = tf.reduce_sum(BCE)
    KLD = -0.5 * tf.reduce_sum(1 + logvar - tf.square(mu) - tf.exp(logvar))
    return BCE + KLD

recon_x = tf.sigmoid(tf.random.normal([64, 784]))
x = tf.sigmoid(tf.random.normal([64, 28, 28]))
mu = tf.random.normal([64, 20])
logvar = tf.random.normal([64, 20])
# Flatten the target tensor to match the shape of recon_x
x = tf.reshape(x, [64, 784])

loss = loss_function(recon_x, x, mu, logvar)
assert loss.numpy() > 0, 'Loss should be positive'

assert loss_function(recon_x, x, mu, logvar).dtype == tf.float32, 'Loss should be a floating-point tensor'

assert tf.math.is_finite(loss), 'Loss should be finite and not NaN/Inf'

x_zeros = tf.zeros_like(x)
assert loss_function(recon_x, x_zeros, mu, logvar).numpy() > 0, 'Loss with zero target should be positive'

recon_zeros = tf.zeros_like(recon_x)
assert loss_function(recon_zeros, x, mu, logvar).numpy() > 0, 'Loss with zero reconstruction should be positive'


# Define the Policy class
#class Policy(nn.Module):
#    def __init__(self):
#        super().__init__()
#        self.affine1 = nn.Linear(4, 128)
#        self.dropout = nn.Dropout(p=0.6)
#        self.affine2 = nn.Linear(128, 2)

class Policy(nn.Module):
    def __init__(self):
        super().__init__()
        self.affine1 = nn.Linear(4, 128)
        self.dropout = nn.Dropout(p=0.6)
        self.affine2 = nn.Linear(128, 2)

        self.saved_log_probs = []
        self.rewards = []

    def forward(self, x):
        x = self.affine1(x)
        x = self.dropout(x)
        x = F.relu(x)
        action_scores = self.affine2(x)
        return F.softmax(action_scores, dim=1)

model = Policy()
input_tensor = torch.randn(32, 4)

output = model(input_tensor)
assert output.shape == (32, 2), f'Expected output shape (32, 2), got {output.shape}'

assert isinstance(model.affine1, nn.Linear), 'affine1 should be an instance of nn.Linear'

assert isinstance(model.affine2, nn.Linear), 'affine2 should be an instance of nn.Linear'

assert isinstance(model.dropout, nn.Dropout), 'dropout should be an instance of nn.Dropout'

assert torch.allclose(output.sum(dim=1), torch.tensor([1.0] * 32)), 'Output probabilities should sum to 1'

# Define the Policy class
#class Policy(Model):
#    def __init__(self):
#        super().__init__()
#        self.fc1 = layers.Dense(128, activation=None)
#        self.dropout = layers.Dropout(0.6)
#        self.fc2 = layers.Dense(2)

class Policy(Model):
    def __init__(self):
        super().__init__()
        self.fc1 = layers.Dense(128, activation=None)
        self.dropout = layers.Dropout(0.6)
        self.fc2 = layers.Dense(2)

    def call(self, inputs):
        x = self.fc1(inputs)
        x = self.dropout(x)
        x = tf.nn.relu(x)
        action_scores = self.fc2(x)
        return tf.nn.softmax(action_scores, axis=1)

model = Policy()
input_tensor = tf.random.normal([32, 4])

assert isinstance(model.fc1, layers.Dense), 'fc1 should be an instance of layers.Dense'

assert isinstance(model.fc2, layers.Dense), 'fc2 should be an instance of layers.Dense'

assert isinstance(model.dropout, layers.Dropout), 'dropout should be an instance of layers.Dropout'

assert tf.reduce_all(tf.abs(tf.reduce_sum(output, axis=1) - 1.0) < 1e-5), 'Output probabilities should sum to 1'


from transformers import BertModel
import torch

model = BertModel.from_pretrained('bert-base-cased')
encoded_sequences = [
    [101, 7592, 999, 102],
    [101, 4658, 1012, 102],
    [101, 3835, 999, 102]
]
model_inputs = torch.tensor(encoded_sequences)
output = model(model_inputs)

assert output.last_hidden_state.shape == (3, 4, 768), f'Expected output shape (3, 4, 768), got {output.last_hidden_state.shape}'

assert output.last_hidden_state is not None, 'Model should return a valid last_hidden_state'

assert model.config.model_type == 'bert', 'The loaded model should be of type BERT'

assert model.config._name_or_path == 'bert-base-cased', f'Expected model to be "bert-base-cased", got {model.config._name_or_path}'

encoded_sequences_2 = [[101, 2057, 2000, 2224, 999, 102], [101, 1005, 1055, 1521, 1005, 102]]
model_inputs_2 = torch.tensor(encoded_sequences_2)
output_2 = model(model_inputs_2)
assert output_2.last_hidden_state.shape == (2, 6, 768), f'Expected output shape (2, 7, 768), got {output_2.last_hidden_state.shape}'

encoded_sequences_3 = [[101, 2023, 2003, 1037, 6429, 999, 102]]
model_inputs_3 = torch.tensor(encoded_sequences_3)
output_3 = model(model_inputs_3)
assert output_3.last_hidden_state.shape == (1, 7, 768), f'Expected output shape (1, 7, 768), got {output_3.last_hidden_state.shape}'

from transformers import TFBertModel
import tensorflow as tf

model = TFBertModel.from_pretrained('bert-base-cased')
encoded_sequences = [
    [101, 7592, 999, 102],
    [101, 4658, 1012, 102],
    [101, 3835, 999, 102]
]
model_inputs = tf.constant(encoded_sequences)
output = model(model_inputs)

encoded_sequences_2 = [[101, 2057, 2000, 2224, 999, 102], [101, 1005, 1055, 1521, 1005, 102]]
model_inputs_2 = tf.constant(encoded_sequences_2)
output_2 = model(model_inputs_2)
assert output_2.last_hidden_state.shape == (2, 6, 768), f'Expected output shape (2, 6, 768), got {output_2.last_hidden_state.shape}'

encoded_sequences_3 = [[101, 2023, 2003, 1037, 6429, 999, 102]]
model_inputs_3 = tf.constant(encoded_sequences_3)
output_3 = model(model_inputs_3)
assert output_3.last_hidden_state.shape == (1, 7, 768), f'Expected output shape (1, 7, 768), got {output_3.last_hidden_state.shape}'


class DeepNN(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        # Define the model layers here

class DeepNN(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 128, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.Conv2d(128, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.Conv2d(64, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.classifier = nn.Sequential(
            nn.Linear(2048, 512),
            nn.ReLU(),
            nn.Dropout(0.1),
            nn.Linear(512, num_classes)
        )

    def forward(self, x):
        x = self.features(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x

model = DeepNN(num_classes=10)
input_tensor = torch.randn(32, 3, 32, 32)

output = model(input_tensor)
assert output.shape == (32, 10), f'Expected output shape (32, 10), got {output.shape}'

assert isinstance(model.features[0], nn.Conv2d), 'First layer should be Conv2d'

assert model.features[0].out_channels == 128, 'First Conv2d layer should have 128 output channels'

assert isinstance(model.classifier[3], nn.Linear), 'Final classifier layer should be Linear with output size of num_classes'

class DeepNN(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        # Define the model layers here

class DeepNN(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = tf.keras.Sequential([
            layers.Conv2D(128, (3, 3), padding='same', activation='relu', input_shape=(32, 32, 3)),
            layers.Conv2D(64, (3, 3), padding='same', activation='relu'),
            layers.MaxPooling2D(pool_size=(2, 2)),
            layers.Conv2D(64, (3, 3), padding='same', activation='relu'),
            layers.Conv2D(32, (3, 3), padding='same', activation='relu'),
            layers.MaxPooling2D(pool_size=(2, 2)),
        ])
        self.classifier = tf.keras.Sequential([
            layers.Flatten(),
            layers.Dense(512, activation='relu'),
            layers.Dropout(0.1),
            layers.Dense(num_classes)
        ])

    def call(self, x):
        x = self.features(x)
        x = self.classifier(x)
        return x

model = DeepNN(num_classes=10)
input_tensor = tf.random.normal([32, 32, 32, 3])

assert isinstance(model.features.layers[0], layers.Conv2D), 'First layer should be Conv2D'

assert model.features.layers[0].filters == 128, 'First Conv2D layer should have 128 filters'

assert isinstance(model.classifier.layers[-1], layers.Dense), 'Final classifier layer should be Dense with output size of num_classes'


class LightNN(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        # Define the model layers here

class LightNN(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(16, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.classifier = nn.Sequential(
            nn.Linear(1024, 256),
            nn.ReLU(),
            nn.Dropout(0.1),
            nn.Linear(256, num_classes)
        )

    def forward(self, x):
        x = self.features(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x

model = LightNN(num_classes=10)
input_tensor = torch.randn(32, 3, 32, 32)

assert model.features[0].out_channels == 16, 'First Conv2d layer should have 16 output channels'

assert isinstance(model.classifier[-1], nn.Linear), 'Final classifier layer should be Linear with output size of num_classes'

class LightNN(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        # Define the model layers here

class LightNN(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = tf.keras.Sequential([
            layers.Conv2D(16, (3, 3), padding='same', activation='relu', input_shape=(32, 32, 3)),
            layers.MaxPooling2D(pool_size=(2, 2)),
            layers.Conv2D(16, (3, 3), padding='same', activation='relu'),
            layers.MaxPooling2D(pool_size=(2, 2)),
        ])
        self.classifier = tf.keras.Sequential([
            layers.Flatten(),
            layers.Dense(256, activation='relu'),
            layers.Dropout(0.1),
            layers.Dense(num_classes)
        ])

    def call(self, x):
        x = self.features(x)
        x = self.classifier(x)
        return x

model = LightNN(num_classes=10)
input_tensor = tf.random.normal([32, 32, 32, 3])

assert model.features.layers[0].filters == 16, 'First Conv2D layer should have 16 filters'


class ModifiedDeepNNCosine(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        # Define the model layers here

class ModifiedDeepNNCosine(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 128, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.Conv2d(128, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.Conv2d(64, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.classifier = nn.Sequential(
            nn.Linear(2048, 512),
            nn.ReLU(),
            nn.Dropout(0.1),
            nn.Linear(512, num_classes)
        )

    def forward(self, x):
        x = self.features(x)
        flattened_conv_output = torch.flatten(x, 1)
        x = self.classifier(flattened_conv_output)
        flattened_conv_output_after_pooling = F.avg_pool1d(flattened_conv_output.unsqueeze(1), 2).squeeze(1)
        return x, flattened_conv_output_after_pooling

model = ModifiedDeepNNCosine(num_classes=10)
input_tensor = torch.randn(32, 3, 32, 32)

output, pooled_output = model(input_tensor)
assert output.shape == (32, 10), f'Expected output shape (32, 10), got {output.shape}'

assert pooled_output.shape == (32, 1024), f'Expected pooled output shape (32, 1024), got {pooled_output.shape}'

class ModifiedDeepNNCosine(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        # Define the model layers here

class ModifiedDeepNNCosine(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = tf.keras.Sequential([
            layers.Conv2D(128, (3, 3), padding='same', activation='relu'),
            layers.Conv2D(64, (3, 3), padding='same', activation='relu'),
            layers.MaxPooling2D((2, 2)),
            layers.Conv2D(64, (3, 3), padding='same', activation='relu'),
            layers.Conv2D(32, (3, 3), padding='same', activation='relu'),
            layers.MaxPooling2D((2, 2)),
        ])
        self.classifier = tf.keras.Sequential([
            layers.Flatten(),
            layers.Dense(512, activation='relu'),
            layers.Dropout(0.1),
            layers.Dense(num_classes)
        ])

    def call(self, x):
        x = self.features(x)
        flattened_conv_output = tf.keras.layers.Flatten()(x)
        output = self.classifier(flattened_conv_output)
        pooled_output = tf.keras.layers.AveragePooling1D(pool_size=2)(tf.expand_dims(flattened_conv_output, axis=-1))
        pooled_output = tf.squeeze(pooled_output, axis=-1)  # Ensure the shape is correct
        return output, pooled_output

model = ModifiedDeepNNCosine(num_classes=10)
input_tensor = tf.random.normal([32, 32, 32, 3])


class ModifiedLightNNCosine(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        # Initialize model layers here

class ModifiedLightNNCosine(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(16, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.classifier = nn.Sequential(
            nn.Linear(1024, 256),
            nn.ReLU(),
            nn.Dropout(0.1),
            nn.Linear(256, num_classes)
        )

    def forward(self, x):
        x = self.features(x)
        flattened_conv_output = torch.flatten(x, 1)
        x = self.classifier(flattened_conv_output)
        return x, flattened_conv_output

model = ModifiedLightNNCosine(num_classes=10)
input_tensor = torch.randn(32, 3, 32, 32)

output, flattened_conv_output = model(input_tensor)
assert output.shape == (32, 10), f'Expected output shape (32, 10), got {output.shape}'

assert flattened_conv_output.shape == (32, 1024), f'Expected flattened_conv_output shape (32, 1024), got {flattened_conv_output.shape}'

class ModifiedLightNNCosine(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        # Initialize model layers here

class ModifiedLightNNCosine(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = tf.keras.Sequential([
            layers.Conv2D(16, (3, 3), padding='same', activation='relu'),
            layers.MaxPooling2D((2, 2)),
            layers.Conv2D(16, (3, 3), padding='same', activation='relu'),
            layers.MaxPooling2D((2, 2)),
        ])
        self.classifier = tf.keras.Sequential([
            layers.Flatten(),
            layers.Dense(256, activation='relu'),
            layers.Dropout(0.1),
            layers.Dense(num_classes)
        ])

    def call(self, x):
        x = self.features(x)
        flattened_conv_output = tf.keras.layers.Flatten()(x)
        output = self.classifier(flattened_conv_output)
        return output, flattened_conv_output

model = ModifiedLightNNCosine(num_classes=10)
input_tensor = tf.random.normal([32, 32, 32, 3])


class ModifiedDeepNNRegressor(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        # Initialize model layers here

class ModifiedDeepNNRegressor(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 128, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.Conv2d(128, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.Conv2d(64, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        self.classifier = nn.Sequential(
            nn.Linear(2048, 512),
            nn.ReLU(),
            nn.Dropout(0.1),
            nn.Linear(512, num_classes)
        )

    def forward(self, x):
        x = self.features(x)
        conv_feature_map = x
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x, conv_feature_map

model = ModifiedDeepNNRegressor(num_classes=10)
input_tensor = torch.randn(32, 3, 32, 32)

output, conv_feature_map = model(input_tensor)
assert output.shape == (32, 10), f'Expected output shape (32, 10), got {output.shape}'

assert conv_feature_map.shape == (32, 32, 8, 8), f'Expected conv_feature_map shape (32, 32, 8, 8), got {conv_feature_map.shape}'

class ModifiedDeepNNRegressor(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        # Initialize model layers here

class ModifiedDeepNNRegressor(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = tf.keras.Sequential([
            layers.Conv2D(128, (3, 3), padding='same', activation='relu'),
            layers.Conv2D(64, (3, 3), padding='same', activation='relu'),
            layers.MaxPooling2D((2, 2)),
            layers.Conv2D(64, (3, 3), padding='same', activation='relu'),
            layers.Conv2D(32, (3, 3), padding='same', activation='relu'),
            layers.MaxPooling2D((2, 2))
        ])
        self.classifier = tf.keras.Sequential([
            layers.Flatten(),
            layers.Dense(512, activation='relu'),
            layers.Dropout(0.1),
            layers.Dense(num_classes)
        ])

    def call(self, x):
        conv_feature_map = self.features(x)
        output = self.classifier(conv_feature_map)
        return output, conv_feature_map

model = ModifiedDeepNNRegressor(num_classes=10)
input_tensor = tf.random.normal([32, 32, 32, 3])

assert conv_feature_map.shape == (32, 8, 8, 32), f'Expected conv_feature_map shape (32, 8, 8, 32), got {conv_feature_map.shape}'


class ModifiedLightNNRegressor(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        # Initialize model layers here

class ModifiedLightNNRegressor(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(16, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.regressor = nn.Sequential(
            nn.Conv2d(16, 32, kernel_size=3, padding=1)
        )
        self.classifier = nn.Sequential(
            nn.Linear(1024, 256),
            nn.ReLU(),
            nn.Dropout(0.1),
            nn.Linear(256, num_classes)
        )

    def forward(self, x):
        x = self.features(x)
        regressor_output = self.regressor(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x, regressor_output

model = ModifiedLightNNRegressor(num_classes=10)
input_tensor = torch.randn(32, 3, 32, 32)

output, regressor_output = model(input_tensor)
assert output.shape == (32, 10), f'Expected output shape (32, 10), got {output.shape}'

assert regressor_output.shape == (32, 32, 8, 8), f'Expected regressor_output shape (32, 32, 8, 8), got {regressor_output.shape}'

assert isinstance(model.features[0], nn.Conv2d), 'First layer should be Conv2d'

class ModifiedLightNNRegressor(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        # Initialize model layers here

class ModifiedLightNNRegressor(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = tf.keras.Sequential([
            layers.Conv2D(16, (3, 3), padding='same', activation='relu'),
            layers.MaxPooling2D((2, 2)),
            layers.Conv2D(16, (3, 3), padding='same', activation='relu'),
            layers.MaxPooling2D((2, 2))
        ])
        self.regressor = tf.keras.Sequential([
            layers.Conv2D(32, (3, 3), padding='same')
        ])
        self.classifier = tf.keras.Sequential([
            layers.Flatten(),
            layers.Dense(256, activation='relu'),
            layers.Dropout(0.1),
            layers.Dense(num_classes)
        ])

    def call(self, x):
        x = self.features(x)
        regressor_output = self.regressor(x)
        x = tf.keras.layers.Flatten()(x)
        output = self.classifier(x)
        return output, regressor_output

model = ModifiedLightNNRegressor(num_classes=10)
input_tensor = tf.random.normal([32, 32, 32, 3])

assert regressor_output.shape == (32, 8, 8, 32), f'Expected regressor_output shape (32, 8, 8, 32), got {regressor_output.shape}'

assert isinstance(model.features.layers[0], layers.Conv2D), 'First layer should be Conv2D'


class BiRNN(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, num_classes):
        super().__init__()
        # Initialize model layers here

class BiRNN(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, num_classes):
        super().__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True, bidirectional=True)
        self.fc = nn.Linear(hidden_size*2, num_classes)  # 2 for bidirection

    def forward(self, x):
        h0 = torch.zeros(self.num_layers*2, x.size(0), self.hidden_size).to(x.device)  # 2 for bidirection
        c0 = torch.zeros(self.num_layers*2, x.size(0), self.hidden_size).to(x.device)
        out, _ = self.lstm(x, (h0, c0))  # out: tensor of shape (batch_size, seq_length, hidden_size*2)
        out = self.fc(out[:, -1, :])
        return out

input_size = 28
hidden_size = 64
num_layers = 2
num_classes = 10
model = BiRNN(input_size, hidden_size, num_layers, num_classes)
input_tensor = torch.randn(32, 10, input_size).to(torch.device('cuda' if torch.cuda.is_available() else 'cpu'))

output = model(input_tensor)
assert output.shape == (32, num_classes), f'Expected output shape (32, {num_classes}), got {output.shape}'

assert isinstance(model.lstm, nn.LSTM), 'The LSTM layer should be of type nn.LSTM'

assert model.lstm.bidirectional == True, 'The LSTM layer should be bidirectional'

assert isinstance(model.fc, nn.Linear), 'The final layer should be a Linear layer with output size of num_classes'

class BiRNN(Model):
    def __init__(self, input_size, hidden_size, num_layers, num_classes):
        super().__init__()
        # Initialize model layers here

class BiRNN(Model):
    def __init__(self, input_size, hidden_size, num_layers, num_classes):
        super().__init__()
        self.lstm = layers.Bidirectional(layers.LSTM(hidden_size, return_sequences=False, recurrent_initializer='glorot_uniform', recurrent_activation='sigmoid', dropout=0.1))
        self.fc = layers.Dense(num_classes)

    def call(self, x):
        out = self.lstm(x)
        out = self.fc(out)
        return out

input_size = 28
hidden_size = 64
num_layers = 2
num_classes = 10
model = BiRNN(input_size, hidden_size, num_layers, num_classes)
input_tensor = tf.random.normal([32, 10, input_size])

assert isinstance(model.lstm, layers.Bidirectional), 'The LSTM layer should be bidirectional'

assert isinstance(model.fc, layers.Dense), 'The final layer should be Dense with output size of num_classes'


class ConvNet(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        # Initialize model layers here

class ConvNet(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2),
            nn.BatchNorm2d(16),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2))
        self.layer2 = nn.Sequential(
            nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),
            nn.BatchNorm2d(32),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2))
        self.fc = nn.Linear(7*7*32, num_classes)

    def forward(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = out.reshape(out.size(0), -1)
        out = self.fc(out)
        return out

model = ConvNet(num_classes=10)
input_tensor = torch.randn(32, 1, 28, 28)

output = model(input_tensor)
assert output.shape == (32, 10), f'Expected output shape (32, 10), got {output.shape}'

assert isinstance(model.layer1[0], nn.Conv2d), 'First layer should be Conv2d'

assert model.layer1[0].out_channels == 16, 'First Conv2d layer should have 16 output channels'

assert isinstance(model.fc, nn.Linear), 'Final layer should be a Linear layer with output size of num_classes'

class ConvNet(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        # Initialize model layers here

class ConvNet(Model):
    def __init__(self, num_classes=10):
        super().__init__()
        self.layer1 = tf.keras.Sequential([
            layers.Conv2D(16, (5, 5), padding='same', activation='relu', input_shape=(28, 28, 1)),
            layers.BatchNormalization(),
            layers.MaxPooling2D(pool_size=(2, 2))
        ])
        self.layer2 = tf.keras.Sequential([
            layers.Conv2D(32, (5, 5), padding='same', activation='relu'),
            layers.BatchNormalization(),
            layers.MaxPooling2D(pool_size=(2, 2))
        ])
        self.fc = layers.Dense(num_classes)

    def call(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = tf.keras.layers.Flatten()(x)
        x = self.fc(x)
        return x

model = ConvNet(num_classes=10)
input_tensor = tf.random.normal([32, 28, 28, 1])

assert isinstance(model.layer1.layers[0], layers.Conv2D), 'First layer should be Conv2D'

assert model.layer1.layers[0].filters == 16, 'First Conv2D layer should have 16 filters'

assert isinstance(model.fc, layers.Dense), 'Final classifier layer should be Dense with output size of num_classes'


class AutoEncoder(nn.Module):
    def __init__(self):
        super().__init__()
        # Define the encoder and decoder layers here

class AutoEncoder(nn.Module):
    def __init__(self):
        super().__init__()

        self.encoder = nn.Sequential(
            nn.Linear(28*28, 128),
            nn.Tanh(),
            nn.Linear(128, 64),
            nn.Tanh(),
            nn.Linear(64, 12),
            nn.Tanh(),
            nn.Linear(12, 3)
        )
        self.decoder = nn.Sequential(
            nn.Linear(3, 12),
            nn.Tanh(),
            nn.Linear(12, 64),
            nn.Tanh(),
            nn.Linear(64, 128),
            nn.Tanh(),
            nn.Linear(128, 28*28),
            nn.Sigmoid()
        )

    def forward(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return encoded, decoded

model = AutoEncoder()
input_tensor = torch.randn(32, 28*28)

encoded, decoded = model(input_tensor)
assert encoded.shape == (32, 3), f'Expected encoded shape (32, 3), got {encoded.shape}'

assert decoded.shape == (32, 28*28), f'Expected decoded shape (32, 28*28), got {decoded.shape}'

assert isinstance(model.encoder[0], nn.Linear), 'First layer in encoder should be Linear'

assert isinstance(model.decoder[-2], nn.Linear), 'Final layer in decoder should be Linear'

class AutoEncoder(Model):
    def __init__(self):
        super().__init__()
        # Define the encoder and decoder layers here

class AutoEncoder(Model):
    def __init__(self):
        super().__init__()
        self.encoder = tf.keras.Sequential([
            layers.Dense(128, activation='tanh'),
            layers.Dense(64, activation='tanh'),
            layers.Dense(12, activation='tanh'),
            layers.Dense(3)
        ])
        self.decoder = tf.keras.Sequential([
            layers.Dense(12, activation='tanh'),
            layers.Dense(64, activation='tanh'),
            layers.Dense(128, activation='tanh'),
            layers.Dense(28*28, activation='sigmoid')
        ])

    def call(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return encoded, decoded

model = AutoEncoder()
input_tensor = tf.random.normal([32, 28*28])

assert isinstance(model.encoder.layers[0], layers.Dense), 'First layer in encoder should be Dense'

assert isinstance(model.decoder.layers[-1], layers.Dense), 'Final layer in decoder should be Dense'


class DenseLayer(nn.Module):
    def __init__(self, in_channels):
        super(DenseLayer, self).__init__()
        # Define the batch normalization and convolutional layers here

class DenseLayer(nn.Module):
    def __init__(self, in_channels):
        super().__init__()
        k=12
        self.BN1 = nn.BatchNorm2d(num_features=in_channels)
        self.conv1 = nn.Conv2d(in_channels=in_channels, out_channels=4*k, kernel_size=1, stride=1, padding=0, bias=False)
        self.BN2 = nn.BatchNorm2d(num_features=4*k)
        self.conv2 = nn.Conv2d(in_channels=4*k, out_channels=k, kernel_size=3, stride=1, padding=1, bias=False)
        self.relu = nn.ReLU()

    def forward(self, x):
        xin = x
        x = self.BN1(x)
        x = self.relu(x)
        x = self.conv1(x)
        x = self.BN2(x)
        x = self.relu(x)
        x = self.conv2(x)
        x = torch.cat([xin, x], 1)
        return x

k=12
model = DenseLayer(in_channels=64)
input_tensor = torch.randn(32, 64, 32, 32)

output = model(input_tensor)
expected_channels = 64 + k
assert output.shape == (32, expected_channels, 32, 32), f'Expected output shape (32, {expected_channels}, 32, 32), got {output.shape}'

assert isinstance(model.BN1, nn.BatchNorm2d), 'BN1 should be an instance of BatchNorm2d'

assert isinstance(model.conv1, nn.Conv2d), 'conv1 should be an instance of Conv2d'

assert isinstance(model.conv2, nn.Conv2d), 'conv2 should be an instance of Conv2d'

class DenseLayer(Model):
    def __init__(self, in_channels):
        super().__init__()
        # Define the batch normalization and convolutional layers here

class DenseLayer(Model):
    def __init__(self, in_channels):
        super().__init__()
        k=12
        self.BN1 = layers.BatchNormalization()
        self.conv1 = layers.Conv2D(4*k, kernel_size=1, strides=1, padding='valid', use_bias=False)
        self.BN2 = layers.BatchNormalization()
        self.conv2 = layers.Conv2D(k, kernel_size=3, strides=1, padding='same', use_bias=False)
        self.relu = layers.ReLU()

    def call(self, x):
        xin = x
        x = self.BN1(x)
        x = self.relu(x)
        x = self.conv1(x)
        x = self.BN2(x)
        x = self.relu(x)
        x = self.conv2(x)
        x = tf.concat([xin, x], axis=-1)
        return x

k = 12
model = DenseLayer(in_channels=64)
input_tensor = tf.random.normal([32, 32, 32, 64])

output = model(input_tensor)
expected_channels = 64 + k
assert output.shape == (32, 32, 32, expected_channels), f'Expected output shape (32, 32, 32, {expected_channels}), got {output.shape}'

assert isinstance(model.BN1, layers.BatchNormalization), 'BN1 should be an instance of BatchNormalization'

assert isinstance(model.conv1, layers.Conv2D), 'conv1 should be an instance of Conv2D'

assert isinstance(model.conv2, layers.Conv2D), 'conv2 should be an instance of Conv2D'


class TransitionLayer(nn.Module):
    def __init__(self, in_channels, compression_factor):
        super().__init__()
        # Define the batch normalization, 1x1 convolution, and average pooling layers here

class TransitionLayer(nn.Module):
    def __init__(self, in_channels, compression_factor):
        super().__init__()
        self.BN = nn.BatchNorm2d(in_channels)
        self.conv1 = nn.Conv2d(in_channels=in_channels, out_channels=int(in_channels * compression_factor), kernel_size=1, stride=1, padding=0, bias=False)
        self.avgpool = nn.AvgPool2d(kernel_size=2, stride=2)

    def forward(self, x):
        x = self.BN(x)
        x = self.conv1(x)
        x = self.avgpool(x)
        return x

compression_factor = 0.5
model = TransitionLayer(in_channels=64, compression_factor=compression_factor)
input_tensor = torch.randn(32, 64, 32, 32)

output = model(input_tensor)
expected_channels = int(64 * compression_factor)
assert output.shape == (32, expected_channels, 16, 16), f'Expected output shape (32, {expected_channels}, 16, 16), got {output.shape}'

assert isinstance(model.BN, nn.BatchNorm2d), 'BN should be an instance of BatchNorm2d'

assert isinstance(model.avgpool, nn.AvgPool2d), 'avgpool should be an instance of AvgPool2d'

class TransitionLayer(Model):
    def __init__(self, in_channels, compression_factor):
        super().__init__()
        # Define the batch normalization, 1x1 convolution, and average pooling layers here

class TransitionLayer(Model):
    def __init__(self, in_channels, compression_factor):
        super().__init__()
        self.BN = layers.BatchNormalization()
        self.conv1 = layers.Conv2D(int(in_channels * compression_factor), kernel_size=1, strides=1, padding='valid', use_bias=False)
        self.avgpool = layers.AvgPool2D(pool_size=2, strides=2)

    def call(self, x):
        x = self.BN(x)
        x = self.conv1(x)
        x = self.avgpool(x)
        return x

compression_factor = 0.5
model = TransitionLayer(in_channels=64, compression_factor=compression_factor)
input_tensor = tf.random.normal([32, 32, 32, 64])

output = model(input_tensor)
expected_channels = int(64 * compression_factor)
assert output.shape == (32, 16, 16, expected_channels), f'Expected output shape (32, 16, 16, {expected_channels}), got {output.shape}'

assert isinstance(model.BN, layers.BatchNormalization), 'BN should be an instance of BatchNormalization'

assert isinstance(model.avgpool, layers.AvgPool2D), 'avgpool should be an instance of AvgPool2D'