diff --git a/.gitignore b/.gitignore index e8bc26f..eb3e7b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /venv -docs/.DS_Store \ No newline at end of file +docs/.DS_Store +diffusion-models/notebooks/mnist_data/ \ No newline at end of file diff --git a/diffusion-models/notebooks/hf_diffusers.ipynb b/diffusion-models/notebooks/hf_diffusers.ipynb index 66089a7..bd18dfc 100644 --- a/diffusion-models/notebooks/hf_diffusers.ipynb +++ b/diffusion-models/notebooks/hf_diffusers.ipynb @@ -9,9 +9,9 @@ "name": "stderr", "output_type": "stream", "text": [ - "/usr/local/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + "/usr/local/lib/python3.10/dist-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n", - "/usr/local/lib/python3.12/site-packages/diffusers/models/transformers/transformer_2d.py:34: FutureWarning: `Transformer2DModelOutput` is deprecated and will be removed in version 1.0.0. Importing `Transformer2DModelOutput` from `diffusers.models.transformer_2d` is deprecated and this will be removed in a future version. Please use `from diffusers.models.modeling_outputs import Transformer2DModelOutput`, instead.\n", + "/usr/local/lib/python3.10/dist-packages/diffusers/models/transformers/transformer_2d.py:34: FutureWarning: `Transformer2DModelOutput` is deprecated and will be removed in version 1.0.0. Importing `Transformer2DModelOutput` from `diffusers.models.transformer_2d` is deprecated and this will be removed in a future version. Please use `from diffusers.models.modeling_outputs import Transformer2DModelOutput`, instead.\n", " deprecate(\"Transformer2DModelOutput\", \"1.0.0\", deprecation_message)\n" ] } @@ -41,15 +41,19 @@ " in_channels=1,\n", " out_channels=1,\n", " layers_per_block=1,\n", - " block_out_channels=(32, 64),\n", + " block_out_channels=(8, 16, 32),\n", " down_block_types=(\n", " \"DownBlock2D\",\n", " \"DownBlock2D\",\n", + " \"DownBlock2D\",\n", " ),\n", " up_block_types=(\n", " \"UpBlock2D\",\n", " \"UpBlock2D\",\n", + " \"UpBlock2D\",\n", " ),\n", + " num_class_embeds=10,\n", + " norm_num_groups=1,\n", ")" ] }, @@ -62,43 +66,63 @@ "data": { "text/plain": [ "UNet2DModel(\n", - " (conv_in): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (conv_in): Conv2d(1, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " (time_proj): Timesteps()\n", " (time_embedding): TimestepEmbedding(\n", - " (linear_1): Linear(in_features=32, out_features=128, bias=True)\n", + " (linear_1): Linear(in_features=8, out_features=32, bias=True)\n", " (act): SiLU()\n", - " (linear_2): Linear(in_features=128, out_features=128, bias=True)\n", + " (linear_2): Linear(in_features=32, out_features=32, bias=True)\n", " )\n", + " (class_embedding): Embedding(10, 32)\n", " (down_blocks): ModuleList(\n", " (0): DownBlock2D(\n", " (resnets): ModuleList(\n", " (0): ResnetBlock2D(\n", - " (norm1): GroupNorm(32, 32, eps=1e-05, affine=True)\n", - " (conv1): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", - " (time_emb_proj): Linear(in_features=128, out_features=32, bias=True)\n", - " (norm2): GroupNorm(32, 32, eps=1e-05, affine=True)\n", + " (norm1): GroupNorm(1, 8, eps=1e-05, affine=True)\n", + " (conv1): Conv2d(8, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (time_emb_proj): Linear(in_features=32, out_features=8, bias=True)\n", + " (norm2): GroupNorm(1, 8, eps=1e-05, affine=True)\n", " (dropout): Dropout(p=0.0, inplace=False)\n", - " (conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (conv2): Conv2d(8, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " (nonlinearity): SiLU()\n", " )\n", " )\n", " (downsamplers): ModuleList(\n", " (0): Downsample2D(\n", - " (conv): Conv2d(32, 32, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))\n", + " (conv): Conv2d(8, 8, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))\n", " )\n", " )\n", " )\n", " (1): DownBlock2D(\n", " (resnets): ModuleList(\n", " (0): ResnetBlock2D(\n", - " (norm1): GroupNorm(32, 32, eps=1e-05, affine=True)\n", - " (conv1): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", - " (time_emb_proj): Linear(in_features=128, out_features=64, bias=True)\n", - " (norm2): GroupNorm(32, 64, eps=1e-05, affine=True)\n", + " (norm1): GroupNorm(1, 8, eps=1e-05, affine=True)\n", + " (conv1): Conv2d(8, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (time_emb_proj): Linear(in_features=32, out_features=16, bias=True)\n", + " (norm2): GroupNorm(1, 16, eps=1e-05, affine=True)\n", + " (dropout): Dropout(p=0.0, inplace=False)\n", + " (conv2): Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (nonlinearity): SiLU()\n", + " (conv_shortcut): Conv2d(8, 16, kernel_size=(1, 1), stride=(1, 1))\n", + " )\n", + " )\n", + " (downsamplers): ModuleList(\n", + " (0): Downsample2D(\n", + " (conv): Conv2d(16, 16, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))\n", + " )\n", + " )\n", + " )\n", + " (2): DownBlock2D(\n", + " (resnets): ModuleList(\n", + " (0): ResnetBlock2D(\n", + " (norm1): GroupNorm(1, 16, eps=1e-05, affine=True)\n", + " (conv1): Conv2d(16, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (time_emb_proj): Linear(in_features=32, out_features=32, bias=True)\n", + " (norm2): GroupNorm(1, 32, eps=1e-05, affine=True)\n", " (dropout): Dropout(p=0.0, inplace=False)\n", - " (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " (nonlinearity): SiLU()\n", - " (conv_shortcut): Conv2d(32, 64, kernel_size=(1, 1), stride=(1, 1))\n", + " (conv_shortcut): Conv2d(16, 32, kernel_size=(1, 1), stride=(1, 1))\n", " )\n", " )\n", " )\n", @@ -107,53 +131,82 @@ " (0): UpBlock2D(\n", " (resnets): ModuleList(\n", " (0): ResnetBlock2D(\n", - " (norm1): GroupNorm(32, 128, eps=1e-05, affine=True)\n", - " (conv1): Conv2d(128, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", - " (time_emb_proj): Linear(in_features=128, out_features=64, bias=True)\n", - " (norm2): GroupNorm(32, 64, eps=1e-05, affine=True)\n", + " (norm1): GroupNorm(1, 64, eps=1e-05, affine=True)\n", + " (conv1): Conv2d(64, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (time_emb_proj): Linear(in_features=32, out_features=32, bias=True)\n", + " (norm2): GroupNorm(1, 32, eps=1e-05, affine=True)\n", " (dropout): Dropout(p=0.0, inplace=False)\n", - " (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " (nonlinearity): SiLU()\n", - " (conv_shortcut): Conv2d(128, 64, kernel_size=(1, 1), stride=(1, 1))\n", + " (conv_shortcut): Conv2d(64, 32, kernel_size=(1, 1), stride=(1, 1))\n", " )\n", " (1): ResnetBlock2D(\n", - " (norm1): GroupNorm(32, 96, eps=1e-05, affine=True)\n", - " (conv1): Conv2d(96, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", - " (time_emb_proj): Linear(in_features=128, out_features=64, bias=True)\n", - " (norm2): GroupNorm(32, 64, eps=1e-05, affine=True)\n", + " (norm1): GroupNorm(1, 48, eps=1e-05, affine=True)\n", + " (conv1): Conv2d(48, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (time_emb_proj): Linear(in_features=32, out_features=32, bias=True)\n", + " (norm2): GroupNorm(1, 32, eps=1e-05, affine=True)\n", " (dropout): Dropout(p=0.0, inplace=False)\n", - " (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " (nonlinearity): SiLU()\n", - " (conv_shortcut): Conv2d(96, 64, kernel_size=(1, 1), stride=(1, 1))\n", + " (conv_shortcut): Conv2d(48, 32, kernel_size=(1, 1), stride=(1, 1))\n", " )\n", " )\n", " (upsamplers): ModuleList(\n", " (0): Upsample2D(\n", - " (conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (conv): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " )\n", " )\n", " )\n", " (1): UpBlock2D(\n", " (resnets): ModuleList(\n", " (0): ResnetBlock2D(\n", - " (norm1): GroupNorm(32, 96, eps=1e-05, affine=True)\n", - " (conv1): Conv2d(96, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", - " (time_emb_proj): Linear(in_features=128, out_features=32, bias=True)\n", - " (norm2): GroupNorm(32, 32, eps=1e-05, affine=True)\n", + " (norm1): GroupNorm(1, 48, eps=1e-05, affine=True)\n", + " (conv1): Conv2d(48, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (time_emb_proj): Linear(in_features=32, out_features=16, bias=True)\n", + " (norm2): GroupNorm(1, 16, eps=1e-05, affine=True)\n", " (dropout): Dropout(p=0.0, inplace=False)\n", - " (conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (conv2): Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " (nonlinearity): SiLU()\n", - " (conv_shortcut): Conv2d(96, 32, kernel_size=(1, 1), stride=(1, 1))\n", + " (conv_shortcut): Conv2d(48, 16, kernel_size=(1, 1), stride=(1, 1))\n", " )\n", " (1): ResnetBlock2D(\n", - " (norm1): GroupNorm(32, 64, eps=1e-05, affine=True)\n", - " (conv1): Conv2d(64, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", - " (time_emb_proj): Linear(in_features=128, out_features=32, bias=True)\n", - " (norm2): GroupNorm(32, 32, eps=1e-05, affine=True)\n", + " (norm1): GroupNorm(1, 24, eps=1e-05, affine=True)\n", + " (conv1): Conv2d(24, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (time_emb_proj): Linear(in_features=32, out_features=16, bias=True)\n", + " (norm2): GroupNorm(1, 16, eps=1e-05, affine=True)\n", " (dropout): Dropout(p=0.0, inplace=False)\n", - " (conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (conv2): Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " (nonlinearity): SiLU()\n", - " (conv_shortcut): Conv2d(64, 32, kernel_size=(1, 1), stride=(1, 1))\n", + " (conv_shortcut): Conv2d(24, 16, kernel_size=(1, 1), stride=(1, 1))\n", + " )\n", + " )\n", + " (upsamplers): ModuleList(\n", + " (0): Upsample2D(\n", + " (conv): Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " )\n", + " )\n", + " )\n", + " (2): UpBlock2D(\n", + " (resnets): ModuleList(\n", + " (0): ResnetBlock2D(\n", + " (norm1): GroupNorm(1, 24, eps=1e-05, affine=True)\n", + " (conv1): Conv2d(24, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (time_emb_proj): Linear(in_features=32, out_features=8, bias=True)\n", + " (norm2): GroupNorm(1, 8, eps=1e-05, affine=True)\n", + " (dropout): Dropout(p=0.0, inplace=False)\n", + " (conv2): Conv2d(8, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (nonlinearity): SiLU()\n", + " (conv_shortcut): Conv2d(24, 8, kernel_size=(1, 1), stride=(1, 1))\n", + " )\n", + " (1): ResnetBlock2D(\n", + " (norm1): GroupNorm(1, 16, eps=1e-05, affine=True)\n", + " (conv1): Conv2d(16, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (time_emb_proj): Linear(in_features=32, out_features=8, bias=True)\n", + " (norm2): GroupNorm(1, 8, eps=1e-05, affine=True)\n", + " (dropout): Dropout(p=0.0, inplace=False)\n", + " (conv2): Conv2d(8, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (nonlinearity): SiLU()\n", + " (conv_shortcut): Conv2d(16, 8, kernel_size=(1, 1), stride=(1, 1))\n", " )\n", " )\n", " )\n", @@ -161,31 +214,31 @@ " (mid_block): UNetMidBlock2D(\n", " (attentions): ModuleList(\n", " (0): Attention(\n", - " (group_norm): GroupNorm(32, 64, eps=1e-05, affine=True)\n", - " (to_q): Linear(in_features=64, out_features=64, bias=True)\n", - " (to_k): Linear(in_features=64, out_features=64, bias=True)\n", - " (to_v): Linear(in_features=64, out_features=64, bias=True)\n", + " (group_norm): GroupNorm(1, 32, eps=1e-05, affine=True)\n", + " (to_q): Linear(in_features=32, out_features=32, bias=True)\n", + " (to_k): Linear(in_features=32, out_features=32, bias=True)\n", + " (to_v): Linear(in_features=32, out_features=32, bias=True)\n", " (to_out): ModuleList(\n", - " (0): Linear(in_features=64, out_features=64, bias=True)\n", + " (0): Linear(in_features=32, out_features=32, bias=True)\n", " (1): Dropout(p=0.0, inplace=False)\n", " )\n", " )\n", " )\n", " (resnets): ModuleList(\n", " (0-1): 2 x ResnetBlock2D(\n", - " (norm1): GroupNorm(32, 64, eps=1e-05, affine=True)\n", - " (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", - " (time_emb_proj): Linear(in_features=128, out_features=64, bias=True)\n", - " (norm2): GroupNorm(32, 64, eps=1e-05, affine=True)\n", + " (norm1): GroupNorm(1, 32, eps=1e-05, affine=True)\n", + " (conv1): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (time_emb_proj): Linear(in_features=32, out_features=32, bias=True)\n", + " (norm2): GroupNorm(1, 32, eps=1e-05, affine=True)\n", " (dropout): Dropout(p=0.0, inplace=False)\n", - " (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " (nonlinearity): SiLU()\n", " )\n", " )\n", " )\n", - " (conv_norm_out): GroupNorm(32, 32, eps=1e-05, affine=True)\n", + " (conv_norm_out): GroupNorm(1, 8, eps=1e-05, affine=True)\n", " (conv_act): SiLU()\n", - " (conv_out): Conv2d(32, 1, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (conv_out): Conv2d(8, 1, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", ")" ] }, @@ -200,7 +253,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -212,152 +265,27 @@ "train_dataset = datasets.MNIST(root='mnist_data', train=True, download=True, transform=transform)\n", "test_dataset = datasets.MNIST(root='mnist_data', train=False, download=True, transform=transform)\n", "\n", - "# train_noisy_dataset = MNISTDataset(train_dataset)\n", - "# test_noisy_dataset = MNISTDataset(test_dataset)\n", - "\n", "train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\n", - "test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "torch.Size([1, 1, 28, 28])" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "sample_image = train_dataset[0][0].unsqueeze(0)\n", - "sample_image.shape" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "output = model(sample_image, timestep=0).sample" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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MQ3Ncxk+6TKUT5I6OjrMmVAoZM7Mnj3bnCkoKDBnqqurzRlJamlpMWcmT55szvzyl780Z9auXWvOSNKrr75qzrgM4SwsLDRnXI53cXGxOSNJv//9782Z5cuXmzMrVqwwZzIyMsyZhoYGc0aSkpOTzZkJEyaYM2+99ZY509nZac5IbgNgrQY6HJorIACAFxQQAMALCggA4AUFBADwggICAHhBAQEAvKCAAABeUEAAAC8oIACAFxQQAMALCggA4AUFBADwYtgOI01MTFRiYuKAt3cZ9tnb22vOuOa6urrMmYMHD5ozBw4cMGdKSkrMGcltoGZ6ero5s3r1anOmpqbGnJGkRYsWmTOf+tSnzBmXAbCf+cxnzBmX4bSS28/TZZddZs5s3rzZnIlEIubMf/7zH3NGchtO6zLkODMz05xxHUbqcl9kHcoai8UGtB1XQAAALyggAIAX5gLauXOnrr32WhUWFioUCp12CR0EgdauXauCggKlpqaqrKzM6VdJAIDRzVxA7e3tKi0t1fr168/48fvuu08PPvigHn74Yb300ksaO3asli5d6vz7SgDA6GR+tKy8vFzl5eVn/FgQBHrggQf03e9+V9ddd50k6Te/+Y3y8vK0efNm3XjjjR9stQCAUSOujwHV1taqoaFBZWVlfe+LRCKaN2+edu3adcZMV1eXotFovxsAYPSLawGd+rvreXl5/d6fl5d31r/JXllZqUgk0ncrKiqK55IAAMOU92fBrVmzRq2trX23uro630sCAAyBuBZQfn6+JKmxsbHf+xsbG/s+9n7hcFgZGRn9bgCA0S+uBVRSUqL8/Hxt3769733RaFQvvfSS5s+fH89dAQBGOPOz4I4dO9ZvzEltba327dunrKwsFRcX64477tAPfvADXXrppSopKdH3vvc9FRYWavny5fFcNwBghDMX0J49e/rNyzo1p2vlypXauHGjvvnNb6q9vV233nqrWlpadM0112jr1q1KSUmJ36oBACOeuYAWLlyoIAjO+vFQKKR7771X99577wdaWE9Pj2kY6bnWdDaWz/9eSUlJTjkrl4GQCQn236r29PSYM5I0depUc+b9jw8OxO7du80Z1//wuAwW3bBhgzmzbds2c+biiy82Z770pS+ZM5L03HPPmTMLFy40Z1paWsyZ4uJic+b55583Z1z3NXHiRHPmxIkT5ozr4+Uu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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", + "test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)\n", "\n", - "plt.imshow(output.squeeze().detach().numpy(), cmap='gray')" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "from diffusers import DDPMScheduler\n", "\n", - "noise_scheduler = DDPMScheduler(num_train_timesteps=150)" + "# " ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ - "noise = torch.randn(sample_image.shape)\n", - "timesteps = torch.LongTensor([20])\n", - "noisy_image = noise_scheduler.add_noise(sample_image, noise, timesteps)\n", - "\n", - "output = model(noisy_image, timestep=50).sample" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA9EAAAFTCAYAAAA+14+JAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABSwUlEQVR4nO3deXzU9bX/8TOZJJN93wkEEgIIhH0RkUXZLSiIrVoXsBaqBSuitOJVAW3F5Wq5Kiq1LaiAUqzgdsUFJBTLIgiyGgmEJZCFhOx7Mt/fH/1lroGQ7wkMTCa8no9HHg+YeefM5zvz/Z6Zk9kshmEYAgAAAAAATHm4egEAAAAAALgLhmgAAAAAAJQYogEAAAAAUGKIBgAAAABAiSEaAAAAAAAlhmgAAAAAAJQYogEAAAAAUGKIBgAAAABAiSEaAAAAAAAlhmg0av78+WKxWC7od5ctWyYWi0WOHj3q3EX9xNGjR8VisciyZcsu2WUAgLMMHz5chg8f7uplAIBbmDp1qrRv3/6yXiaPLdEcDNGtzP79++XOO++UNm3aiM1mk7i4OLnjjjtk//79rl6aS2zcuFEsFou8//77rl4KgBau/g+APj4+cvLkyXPOHz58uHTv3t0FK2s+eh+An6rvb/U/Pj4+EhcXJ2PGjJGXX35ZSkpKXL1Et0F/hQhDdKvywQcfSJ8+fWT9+vVyzz33yGuvvSb33nuvfP3119KnTx9Zs2aNutbjjz8uFRUVF7SOu+66SyoqKiQhIeGCfh8AXKmqqkqeffZZp9b84osv5IsvvnBqTQBorqeeekreeecdef311+WBBx4QEZFZs2ZJSkqK7Nmzx8Wr+z9vvvmmpKWluXoZwHl5unoBcI7Dhw/LXXfdJYmJibJp0yaJjIx0nPfggw/KkCFD5K677pI9e/ZIYmLieeuUlZWJv7+/eHp6iqfnhe0eVqtVrFbrBf0uALhar1695M0335S5c+dKXFycU2p6e3s7pQ4AXIxx48ZJv379HP+fO3eubNiwQcaPHy833nijHDx4UHx9fV24wv/w8vJy9RKAJvFMdCvxwgsvSHl5ufzlL39pMECLiERERMiSJUukrKxMnn/+ecfp9e97PnDggPzyl7+U0NBQufbaaxuc91MVFRXyu9/9TiIiIiQwMFBuvPFGOXnypFgsFpk/f74j19h7otu3by/jx4+XzZs3y4ABA8THx0cSExPl7bffbnAZZ86ckUceeURSUlIkICBAgoKCZNy4cfL999876Zr6v2378ccf5c4775Tg4GCJjIyUJ554QgzDkBMnTshNN90kQUFBEhMTIy+++GKD36+urpYnn3xS+vbtK8HBweLv7y9DhgyRr7/++pzLys/Pl7vuukuCgoIkJCREpkyZIt9//32j77n54Ycf5JZbbpGwsDDx8fGRfv36yUcffeS07Qag89hjj0ldXZ3q2eja2lp5+umnJSkpSWw2m7Rv314ee+wxqaqqapBr7D3Rr7zyinTr1k38/PwkNDRU+vXrJytXrhQRka+//losFkujryBauXKlWCwW2bJlS7O2i94HoDHXX3+9PPHEE3Ls2DFZvnx5g/M0x2f9475vvvlGZs+eLZGRkeLv7y+TJk2S06dPn3N5r732mnTr1s3xtsMZM2ZIYWFhg0xj74l+7733pG/fvhIYGChBQUGSkpIi//M//9MgU1hYKLNmzZK2bduKzWaTjh07ynPPPSd2u/2c3NSpUyU4ONjRo85eQ3PQX688DNGtxMcffyzt27eXIUOGNHr+0KFDpX379vLpp5+ec97Pf/5zKS8vl2eeeUamTZt23suYOnWqvPLKK3LDDTfIc889J76+vvKzn/1Mvcb09HS55ZZbZNSoUfLiiy9KaGioTJ06tcH7tY8cOSJr166V8ePHy0svvSRz5syRvXv3yrBhw+TUqVPqy9K49dZbxW63y7PPPisDBw6UP/7xj7Jo0SIZNWqUtGnTRp577jnp2LGjPPLII7Jp0ybH7xUXF8tf//pXGT58uDz33HMyf/58OX36tIwZM0Z2797tyNntdpkwYYK8++67MmXKFPnTn/4kWVlZMmXKlHPWsn//frn66qvl4MGD8uijj8qLL74o/v7+MnHixGa9DB/AxevQoYPcfffd8uabb5r2nV//+tfy5JNPSp8+feTPf/6zDBs2TBYuXCi33XZbk7/35ptvyu9+9zvp2rWrLFq0SBYsWCC9evWSbdu2ich/hu62bdvKihUrzvndFStWSFJSkgwaNOiCto/eB+Bsd911l4hIg7edNPf4fOCBB+T777+XefPmyf333y8ff/yxzJw5s0Fm/vz5MmPGDImLi5MXX3xRJk+eLEuWLJHRo0dLTU3Nedf35Zdfyu233y6hoaHy3HPPybPPPivDhw+Xb775xpEpLy+XYcOGyfLly+Xuu++Wl19+WQYPHixz586V2bNnO3KGYchNN90k77zzjtx5553yxz/+UTIzMxvtUc1Ff72CGHB7hYWFhogYN910U5O5G2+80RARo7i42DAMw5g3b54hIsbtt99+Trb+vHo7d+40RMSYNWtWg9zUqVMNETHmzZvnOG3p0qWGiBgZGRmO0xISEgwRMTZt2uQ4LTc317DZbMbDDz/sOK2ystKoq6trcBkZGRmGzWYznnrqqQaniYixdOnSJrf566+/NkTEWL169TnbNn36dMdptbW1Rnx8vGGxWIxnn33WcXpBQYHh6+trTJkypUG2qqqqweUUFBQY0dHRxq9+9SvHaf/85z8NETEWLVrkOK2urs64/vrrz1n7iBEjjJSUFKOystJxmt1uN6655hojOTm5yW0E4Bz1vevbb781Dh8+bHh6ehq/+93vHOcPGzbM6Natm+P/u3fvNkTE+PWvf92gziOPPGKIiLFhw4YGvzts2DDH/2+66aYGtRozd+5cw2azGYWFhY7TcnNzDU9PzwY9tzH0PgA/9dP+dj7BwcFG7969Hf/XHp/1tUeOHGnY7XbH6Q899JBhtVodPSw3N9fw9vY2Ro8e3eCx3quvvmqIiPH3v//dcdqUKVOMhIQEx/8ffPBBIygoyKitrT3v+p9++mnD39/f+PHHHxuc/uijjxpWq9U4fvy4YRiGsXbtWkNEjOeff96Rqa2tNYYMGcJjS6jxTHQrUP+JioGBgU3m6s8vLi5ucPp9991nehnr1q0TEZHf/va3DU6v/1AKja5duzZ4pjwyMlI6d+4sR44ccZxms9nEw+M/u2VdXZ3k5+dLQECAdO7cWb777jv1ZWn8+te/dvzbarVKv379xDAMuffeex2nh4SEnLNGq9XqeH+j3W6XM2fOSG1trfTr16/BGtetWydeXl4Nnt338PCQGTNmNFjHmTNnZMOGDfKLX/xCSkpKJC8vT/Ly8iQ/P1/GjBkjhw4davSTggFcOomJiXLXXXfJX/7yF8nKymo087//+78iIg2e4RARefjhh0VEGn3lT72QkBDJzMyUb7/99ryZu+++W6qqqhp8AuyqVauktrZW7rzzTvW2nI3eB6AxAQEBjseUF3J8Tp8+vcFbAYcMGSJ1dXVy7NgxERH56quvpLq6WmbNmuV4rCciMm3aNAkKCjLtmWVlZfLll1+eN7N69WoZMmSIhIaGOtabl5cnI0eOlLq6Osczv//7v/8rnp6ecv/99zt+12q1Nusx7fnQX68cDNGtQP1wbPb1BOcbtjt06GB6GceOHRMPD49zsh07dlSvs127duecFhoaKgUFBY7/2+12+fOf/yzJyclis9kkIiJCIiMjZc+ePVJUVKS+rAtZT3BwsPj4+EhERMQ5p/90jSIib731lvTo0UN8fHwkPDxcIiMj5dNPP22wxmPHjklsbKz4+fk1+N2zr7P09HQxDEOeeOIJiYyMbPAzb948ERHJzc296O0F0DyPP/641NbWnve90fV98exjOiYmRkJCQhwPHBvzhz/8QQICAmTAgAGSnJwsM2bMaPCyRBGRLl26SP/+/Ru8pHvFihVy9dVXN6v3no3eB6AxpaWljseIF3J8nt1bQkNDRUQcfaS+J3bu3LlBztvbWxITE5vsmb/97W+lU6dOMm7cOImPj5df/epXjid46h06dEjWrVt3znpHjhzZYL31PSogIKDB75+9rgtBf71y8OncrUBwcLDExsaafjXBnj17pE2bNhIUFNTg9Mv1KYzn+8RuwzAc/37mmWfkiSeekF/96lfy9NNPS1hYmHh4eMisWbPO+VCIS7EezRqXL18uU6dOlYkTJ8qcOXMkKipKrFarLFy4UA4fPtzsddRv1yOPPCJjxoxpNHMxD5gBXJjExES588475S9/+Ys8+uij582d/SGMGldddZWkpaXJJ598IuvWrZN//vOf8tprr8mTTz4pCxYscOTuvvtuefDBByUzM1Oqqqpk69at8uqrr17Q9tSj9wE4W2ZmphQVFTmOuQs5PjV95EJFRUXJ7t275fPPP5fPPvtMPvvsM1m6dKncfffd8tZbbznWPGrUKPn973/faI1OnTpd9DrM0F+vHAzRrcT48ePlzTfflM2bNzs+Yfun/vWvf8nRo0flN7/5zQXVT0hIELvdLhkZGZKcnOw4PT09/YLX3Jj3339frrvuOvnb3/7W4PTCwsJz/ornKu+//74kJibKBx980ODBc/1f9uolJCTI119/LeXl5Q3+Ynj2dVb/lWNeXl6Ov5YCaBkef/xxWb58uTz33HPnnFffFw8dOiRXXXWV4/ScnBwpLCyUhISEJmv7+/vLrbfeKrfeeqtUV1fLzTffLH/6059k7ty54uPjIyIit912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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(12, 4))\n", - "\n", - "ax1.imshow(sample_image.squeeze().detach().numpy(), cmap='gray')\n", - "ax1.set_title('Original Image')\n", - "\n", - "ax2.imshow(noisy_image.squeeze().detach().numpy(), cmap='gray')\n", - "ax2.set_title('Noisy Image')\n", - "\n", - "ax3.imshow(output.squeeze().detach().numpy(), cmap='gray')\n", - "ax3.set_title('Denoised Image')\n", + "from diffusers import DDPMScheduler\n", "\n", - "plt.show()" + "noise_scheduler = DDPMScheduler(num_train_timesteps=150) " ] }, { "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "tensor(1.0710, grad_fn=)\n" - ] - } - ], - "source": [ - "noise_pred = model(noisy_image, timesteps).sample\n", - "loss = F.mse_loss(noise_pred, noise)\n", - "print(loss)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -366,7 +294,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -392,30 +320,72 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "0it [00:00, ?it/s]/usr/local/lib/python3.12/site-packages/diffusers/configuration_utils.py:140: FutureWarning: Accessing config attribute `num_train_timesteps` directly via 'DDPMScheduler' object attribute is deprecated. Please access 'num_train_timesteps' over 'DDPMScheduler's config object instead, e.g. 'scheduler.config.num_train_timesteps'.\n", + "0it [00:00, ?it/s]/usr/local/lib/python3.10/dist-packages/diffusers/configuration_utils.py:140: FutureWarning: Accessing config attribute `num_train_timesteps` directly via 'DDPMScheduler' object attribute is deprecated. Please access 'num_train_timesteps' over 'DDPMScheduler's config object instead, e.g. 'scheduler.config.num_train_timesteps'.\n", " deprecate(\"direct config name access\", \"1.0.0\", deprecation_message, standard_warn=False)\n", - "1875it [26:23, 1.18it/s]\n" + "1875it [04:51, 6.43it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 0 Loss: 0.059813931584358215\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "1875it [04:47, 6.52it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1 Loss: 0.047683872282505035\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "1875it [04:52, 6.40it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 2 Loss: 0.034084219485521317\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "1875it [05:02, 6.20it/s]\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "Epoch 0 Loss: 0.042306363582611084\n" + "Epoch 3 Loss: 0.039008501917123795\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "569it [08:01, 1.18it/s]\n" + "57it [00:09, 6.02it/s]\n" ] }, { @@ -425,10 +395,20 @@ "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[24], line 14\u001b[0m\n\u001b[1;32m 12\u001b[0m noise_pred \u001b[38;5;241m=\u001b[39m model(noisy_images, timesteps, return_dict\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m)[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m 13\u001b[0m loss \u001b[38;5;241m=\u001b[39m F\u001b[38;5;241m.\u001b[39mmse_loss(noise_pred, noise)\n\u001b[0;32m---> 14\u001b[0m \u001b[43mloss\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbackward\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 15\u001b[0m optimizer\u001b[38;5;241m.\u001b[39mstep()\n\u001b[1;32m 16\u001b[0m lr_scheduler\u001b[38;5;241m.\u001b[39mstep()\n", - "File \u001b[0;32m/usr/local/lib/python3.12/site-packages/torch/_tensor.py:525\u001b[0m, in \u001b[0;36mTensor.backward\u001b[0;34m(self, gradient, retain_graph, create_graph, inputs)\u001b[0m\n\u001b[1;32m 515\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m has_torch_function_unary(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 516\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m handle_torch_function(\n\u001b[1;32m 517\u001b[0m Tensor\u001b[38;5;241m.\u001b[39mbackward,\n\u001b[1;32m 518\u001b[0m (\u001b[38;5;28mself\u001b[39m,),\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 523\u001b[0m inputs\u001b[38;5;241m=\u001b[39minputs,\n\u001b[1;32m 524\u001b[0m )\n\u001b[0;32m--> 525\u001b[0m \u001b[43mtorch\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mautograd\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbackward\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 526\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgradient\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mretain_graph\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcreate_graph\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43minputs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minputs\u001b[49m\n\u001b[1;32m 527\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m/usr/local/lib/python3.12/site-packages/torch/autograd/__init__.py:267\u001b[0m, in \u001b[0;36mbackward\u001b[0;34m(tensors, grad_tensors, retain_graph, create_graph, grad_variables, inputs)\u001b[0m\n\u001b[1;32m 262\u001b[0m retain_graph \u001b[38;5;241m=\u001b[39m create_graph\n\u001b[1;32m 264\u001b[0m \u001b[38;5;66;03m# The reason we repeat the same comment below is that\u001b[39;00m\n\u001b[1;32m 265\u001b[0m \u001b[38;5;66;03m# some Python versions print out the first line of a multi-line function\u001b[39;00m\n\u001b[1;32m 266\u001b[0m \u001b[38;5;66;03m# calls in the traceback and some print out the last line\u001b[39;00m\n\u001b[0;32m--> 267\u001b[0m \u001b[43m_engine_run_backward\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 268\u001b[0m \u001b[43m \u001b[49m\u001b[43mtensors\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 269\u001b[0m \u001b[43m \u001b[49m\u001b[43mgrad_tensors_\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 270\u001b[0m \u001b[43m \u001b[49m\u001b[43mretain_graph\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 271\u001b[0m \u001b[43m \u001b[49m\u001b[43mcreate_graph\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 272\u001b[0m \u001b[43m \u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 273\u001b[0m \u001b[43m \u001b[49m\u001b[43mallow_unreachable\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 274\u001b[0m \u001b[43m \u001b[49m\u001b[43maccumulate_grad\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 275\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m/usr/local/lib/python3.12/site-packages/torch/autograd/graph.py:744\u001b[0m, in \u001b[0;36m_engine_run_backward\u001b[0;34m(t_outputs, *args, **kwargs)\u001b[0m\n\u001b[1;32m 742\u001b[0m unregister_hooks \u001b[38;5;241m=\u001b[39m _register_logging_hooks_on_whole_graph(t_outputs)\n\u001b[1;32m 743\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 744\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mVariable\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_execution_engine\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun_backward\u001b[49m\u001b[43m(\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# Calls into the C++ engine to run the backward pass\u001b[39;49;00m\n\u001b[1;32m 745\u001b[0m \u001b[43m \u001b[49m\u001b[43mt_outputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\n\u001b[1;32m 746\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# Calls into the C++ engine to run the backward pass\u001b[39;00m\n\u001b[1;32m 747\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 748\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m attach_logging_hooks:\n", + "Cell \u001b[0;32mIn[8], line 13\u001b[0m\n\u001b[1;32m 10\u001b[0m timesteps \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mrandint(\u001b[38;5;241m0\u001b[39m, noise_scheduler\u001b[38;5;241m.\u001b[39mnum_train_timesteps, (bs,), device\u001b[38;5;241m=\u001b[39mclean_images\u001b[38;5;241m.\u001b[39mdevice)\u001b[38;5;241m.\u001b[39mlong()\n\u001b[1;32m 11\u001b[0m noisy_images \u001b[38;5;241m=\u001b[39m noise_scheduler\u001b[38;5;241m.\u001b[39madd_noise(clean_images, noise, timesteps)\n\u001b[0;32m---> 13\u001b[0m noise_pred \u001b[38;5;241m=\u001b[39m \u001b[43mmodel\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnoisy_images\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimesteps\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlabels\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mreturn_dict\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m)\u001b[49m[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m 14\u001b[0m loss \u001b[38;5;241m=\u001b[39m F\u001b[38;5;241m.\u001b[39mmse_loss(noise_pred, noise)\n\u001b[1;32m 15\u001b[0m loss\u001b[38;5;241m.\u001b[39mbackward()\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py:1532\u001b[0m, in \u001b[0;36mModule._wrapped_call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1530\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compiled_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs) \u001b[38;5;66;03m# type: ignore[misc]\u001b[39;00m\n\u001b[1;32m 1531\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1532\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_impl\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py:1541\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1536\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[1;32m 1537\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[1;32m 1538\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks\n\u001b[1;32m 1539\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[1;32m 1540\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[0;32m-> 1541\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mforward_call\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1543\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1544\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/diffusers/models/unets/unet_2d.py:329\u001b[0m, in \u001b[0;36mUNet2DModel.forward\u001b[0;34m(self, sample, timestep, class_labels, return_dict)\u001b[0m\n\u001b[1;32m 327\u001b[0m sample, skip_sample \u001b[38;5;241m=\u001b[39m upsample_block(sample, res_samples, emb, skip_sample)\n\u001b[1;32m 328\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 329\u001b[0m sample \u001b[38;5;241m=\u001b[39m \u001b[43mupsample_block\u001b[49m\u001b[43m(\u001b[49m\u001b[43msample\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mres_samples\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43memb\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 331\u001b[0m \u001b[38;5;66;03m# 6. post-process\u001b[39;00m\n\u001b[1;32m 332\u001b[0m sample \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconv_norm_out(sample)\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py:1532\u001b[0m, in \u001b[0;36mModule._wrapped_call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1530\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compiled_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs) \u001b[38;5;66;03m# type: ignore[misc]\u001b[39;00m\n\u001b[1;32m 1531\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1532\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_impl\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py:1541\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1536\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[1;32m 1537\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[1;32m 1538\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks\n\u001b[1;32m 1539\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[1;32m 1540\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[0;32m-> 1541\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mforward_call\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1543\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1544\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/diffusers/models/unets/unet_2d_blocks.py:2673\u001b[0m, in \u001b[0;36mUpBlock2D.forward\u001b[0;34m(self, hidden_states, res_hidden_states_tuple, temb, upsample_size, *args, **kwargs)\u001b[0m\n\u001b[1;32m 2669\u001b[0m hidden_states \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mutils\u001b[38;5;241m.\u001b[39mcheckpoint\u001b[38;5;241m.\u001b[39mcheckpoint(\n\u001b[1;32m 2670\u001b[0m create_custom_forward(resnet), hidden_states, temb\n\u001b[1;32m 2671\u001b[0m )\n\u001b[1;32m 2672\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 2673\u001b[0m hidden_states \u001b[38;5;241m=\u001b[39m \u001b[43mresnet\u001b[49m\u001b[43m(\u001b[49m\u001b[43mhidden_states\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtemb\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2675\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mupsamplers \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 2676\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m upsampler \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mupsamplers:\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py:1532\u001b[0m, in \u001b[0;36mModule._wrapped_call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1530\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compiled_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs) \u001b[38;5;66;03m# type: ignore[misc]\u001b[39;00m\n\u001b[1;32m 1531\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1532\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_impl\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py:1541\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1536\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[1;32m 1537\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[1;32m 1538\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks\n\u001b[1;32m 1539\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[1;32m 1540\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[0;32m-> 1541\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mforward_call\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1543\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1544\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/diffusers/models/resnet.py:345\u001b[0m, in \u001b[0;36mResnetBlock2D.forward\u001b[0;34m(self, input_tensor, temb, *args, **kwargs)\u001b[0m\n\u001b[1;32m 343\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtime_emb_proj \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 344\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mskip_time_act:\n\u001b[0;32m--> 345\u001b[0m temb \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mnonlinearity\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtemb\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 346\u001b[0m temb \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtime_emb_proj(temb)[:, :, \u001b[38;5;28;01mNone\u001b[39;00m, \u001b[38;5;28;01mNone\u001b[39;00m]\n\u001b[1;32m 348\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtime_embedding_norm \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdefault\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py:1532\u001b[0m, in \u001b[0;36mModule._wrapped_call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1530\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compiled_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs) \u001b[38;5;66;03m# type: ignore[misc]\u001b[39;00m\n\u001b[1;32m 1531\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1532\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_impl\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py:1541\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1536\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[1;32m 1537\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[1;32m 1538\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks\n\u001b[1;32m 1539\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[1;32m 1540\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[0;32m-> 1541\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mforward_call\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1543\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1544\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/torch/nn/modules/activation.py:396\u001b[0m, in \u001b[0;36mSiLU.forward\u001b[0;34m(self, input)\u001b[0m\n\u001b[1;32m 395\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mforward\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;28minput\u001b[39m: Tensor) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Tensor:\n\u001b[0;32m--> 396\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mF\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msilu\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43minplace\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minplace\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/torch/nn/functional.py:2102\u001b[0m, in \u001b[0;36msilu\u001b[0;34m(input, inplace)\u001b[0m\n\u001b[1;32m 2100\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m inplace:\n\u001b[1;32m 2101\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m torch\u001b[38;5;241m.\u001b[39m_C\u001b[38;5;241m.\u001b[39m_nn\u001b[38;5;241m.\u001b[39msilu_(\u001b[38;5;28minput\u001b[39m)\n\u001b[0;32m-> 2102\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mtorch\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_C\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_nn\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msilu\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m)\u001b[49m\n", "\u001b[0;31mKeyboardInterrupt\u001b[0m: " ] } @@ -441,11 +421,12 @@ " for i, (clean_images, labels) in tqdm(enumerate(train_loader)):\n", " noise = torch.randn(clean_images.shape)\n", " bs = clean_images.shape[0]\n", + " labels = labels\n", "\n", " timesteps = torch.randint(0, noise_scheduler.num_train_timesteps, (bs,), device=clean_images.device).long()\n", " noisy_images = noise_scheduler.add_noise(clean_images, noise, timesteps)\n", "\n", - " noise_pred = model(noisy_images, timesteps, return_dict=False)[0]\n", + " noise_pred = model(noisy_images, timesteps, labels, return_dict=False)[0]\n", " loss = F.mse_loss(noise_pred, noise)\n", " loss.backward()\n", " optimizer.step()\n", @@ -458,60 +439,89 @@ }, { "cell_type": "code", - "execution_count": 90, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ - "batch = next(iter(train_loader))" + "import numpy as np" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 18, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "torch._C.Generator" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "from diffusers import DDPMPipeline" + "type(torch.manual_seed(42))" ] }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ - "pipeline = DDPMPipeline(unet=model, scheduler=noise_scheduler)\n" + "def inference(model: UNet2DModel,\n", + " scheduler: DDPMScheduler,\n", + " batch_size: int,\n", + " generator: torch._C.Generator,\n", + " num_inference_steps: int,\n", + " label: int) -> np.ndarray:\n", + " \n", + " image_shape = (batch_size, 1, 28, 28)\n", + " labels = torch.full((batch_size,), label)\n", + "\n", + " image = torch.randn(image_shape)\n", + "\n", + " # set step values\n", + " scheduler.set_timesteps(num_inference_steps)\n", + "\n", + " for t in scheduler.timesteps:\n", + " # 1. predict noise model_output\n", + " model_output = model(image, t, labels).sample\n", + "\n", + " # 2. compute previous image: x_t -> x_t-1\n", + " image = scheduler.step(model_output, t, image, generator=generator).prev_sample\n", + "\n", + " image = (image / 2 + 0.5).clamp(0, 1)\n", + " image = image.permute(0, 2, 3, 1)\n", + "\n", + " return image.detach().numpy()" ] }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 14, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "100%|██████████| 150/150 [00:05<00:00, 28.16it/s]\n" - ] - } - ], + "outputs": [], "source": [ - "images = pipeline(\n", - " batch_size=10,\n", - " generator=torch.manual_seed(42),\n", - " num_inference_steps=150,\n", - ").images" + "images = inference(model=model,\n", + " scheduler=noise_scheduler,\n", + " batch_size=10,\n", + " generator=torch.manual_seed(42),\n", + " num_inference_steps=150,\n", + " label=3)" ] }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 15, "metadata": {}, "outputs": [ { "data": { - "image/png": "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", + "image/png": "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IwIAAAAAAGhGIwIAAAAAAGhGIwIAAAAAAGhmLg2Ox+OW49gmJXM2HA57WSs938997nOj3F577VXM/P7v/35Ua/PmzVGO+tI1ti2qeX1xvy7mNTlmF+cxnYtf+ZVfKWa23377qNa1115bzNx4441RLZi09Dqtec3X3LNWV1ejWq94xSuKmXe84x1RrdnZ2WLmc5/7XFQr2T8Gg+wZ8NnPfnZUa35+vpi56667olrvec97ipn0HNVU8/5Te11DzbUy7evusMMOi3LJ/rzjjjtGtV772tcWM1u3bo1qrQXWax1d/PZJv6/tsMMOUe5Zz3pWlHvve99bzKTz+qlPfaqYueGGG6JaiS6eiWvyPab//EcEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQzFzXA9iWDYfDKpnBYDAYj8fFzGg0imolnvjEJ0a5//pf/2uUu/TSS4uZM888M6pVUzL/ydyvFeZistbCfNf8jTX30y6OuXHjxqjWv/t3/y7KJf70T/+0mLn99tujWulcpLnEWrhG1qrk3HZxzae1krHNzGR/D3T22WcXMzvvvHNU641vfGMxc9RRR0W1as5/Oq/XXXddMXPCCSdEtS666KIol6i5r3Wh5vUGg8Hk11TNvfmP//iPo1onnnhilLvrrruKmWOOOSaq9bnPfa6YmZ2djWqtBTXXBXV08exwyCGHFDPJO9FgMBjst99+UW51dbWYueWWW6JaJ598cpXjDQbZnKXPp97D2uji/WbS/EcEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQjEYEAAAAAADQzHA8Ho+T4Pz8fOuxdG44HEa5cMoG69atK2Z23nnnqNb1119fzKTjP/roo4uZs846K6p13333RbmnP/3pxcy1114b1Up/J91ZXl7uegjVzc3NRblkf6i91/APupjX9JhPfepTi5kTTjghqvWyl72smLn44oujWr/4i79YzKyurka11sJ6Tc/3yspK45FM1sLCQtdD+CethTU3GGS/c5dddolqJXvRoYceGtV67nOfG+X22GOPYuarX/1qVOuv/uqvipk//dM/jWrVXD/TvhZr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", "text/plain": [ "
" ] @@ -522,6 +532,7 @@ ], "source": [ "# show images\n", + "import matplotlib.pyplot as plt\n", "fig, ax = plt.subplots(2, 5, figsize=(20, 8))\n", "for i in range(10):\n", " ax[i // 5, i % 5].imshow(images[i], cmap='gray')\n", @@ -552,7 +563,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.3" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/diffusion-models/requirements.txt b/diffusion-models/requirements.txt index cdc2b5a..918624e 100644 --- a/diffusion-models/requirements.txt +++ b/diffusion-models/requirements.txt @@ -1,4 +1,6 @@ torch==2.3.0 torchvision==0.18.0 matplotlib==3.9.0 -seaborn==0.13.2 \ No newline at end of file +seaborn==0.13.2 +diffusers==0.28.2 +transformers==4.41.2 \ No newline at end of file diff --git a/docs/multi_2/subpage_2.md b/docs/hf_diffusers/hf_ecg_gen.md similarity index 100% rename from docs/multi_2/subpage_2.md rename to docs/hf_diffusers/hf_ecg_gen.md diff --git a/docs/hf_diffusers/hf_mnist_gen.md b/docs/hf_diffusers/hf_mnist_gen.md new file mode 100644 index 0000000..e8f08a3 --- /dev/null +++ b/docs/hf_diffusers/hf_mnist_gen.md @@ -0,0 +1,49 @@ +In this section we will introduce a core component of the Diffusers library `UNet2DModel`. This page will closely follow the notebook `hf_diffusers_mnist.ipynb`, so if you're interested in a quick run through and want to play around yourself, then check that out. Here, we will go through the code in more detail and explain the different components of the model, but feel free to refer back to this page. + + + +## `UNet2DModel` +The `UNet2DModel` is a 2D U-Net model that is used for image generation. It abstracts out all of the annoying details of building the model, and allows you to focus on the important parts of your project. + + +``` python +model = UNet2DModel( + sample_size=28, # (1) + in_channels=1, # (2) + out_channels=1, # (3) + layers_per_block=1, # (4) + block_out_channels=(8, 16, 32), # (5) + down_block_types=( + "DownBlock2D", + "DownBlock2D", + "DownBlock2D", + ), + up_block_types=( + "UpBlock2D", + "UpBlock2D", + "UpBlock2D", + ), + num_class_embeds=10, # (6) + norm_num_groups=1, # (7) +) +``` + +1. The size of the input image. In this case, it is 28x28 pixels +2. The number of channels in the input image. In this case, it is 1, as the images are grayscale, but you would use 3 for RGB images +3. The number of channels in the output image. In this case, it is 1, as the images are grayscale, but you would use 3 for RGB images +4. The number of layers in each block +5. The number of output channels in each block - in a convolutional neural network, the number of channels is the number of filters that are applied to the input image. +6. The number of classes your dataset has if you are doing conditional generation. +7. The number of groups to use for the normalization layer. This is a hyperparameter that you can tune to improve the performance of your model. + +There are a number of additional parameters, but these are the most important ones to understand when you are getting started with the `UNet2DModel`. Let's look at the block types in more detail, and some of the additional paramters + +## Further reading +
+ +- :fontawesome-solid-book-open:{ .lg .middle } [__CI/CD - Pre-commit resources__](../resources/references.md#pre-commit) + + --- + Information on GitHub Actions, Black, Flake8, Mypy, Isort, and Git Hooks + +
\ No newline at end of file diff --git a/docs/hf_diffusers/index.md b/docs/hf_diffusers/index.md new file mode 100644 index 0000000..8acff67 --- /dev/null +++ b/docs/hf_diffusers/index.md @@ -0,0 +1,4 @@ +# Hugging Face Diffusers +In this section, we make life easy for ourselves and use the Hugging Face Diffusers Library. We will look at two main tasks: image generation and ECG generation. We will start with image generation, and in doing so, we'll walk through most of the building blocks required to understand the second task. + +Let's get started! \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index f8da25f..4cb81ab 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,9 +2,9 @@ Logo -# COURSE TITLE +# Introduction to diffusion models in generative AI -Welcome to the material for COURSE NAME. +Welcome to the material for Introduction to diffusion models in generative AI. Please check the [official Mkdocs Material documentation](https://squidfunk.github.io/mkdocs-material/) for more information on how to use this template. diff --git a/docs/multi_2/index.md b/docs/multi_2/index.md deleted file mode 100644 index 65f7a9a..0000000 --- a/docs/multi_2/index.md +++ /dev/null @@ -1,2 +0,0 @@ -# Main landing page -You can see the links to subpages on the left. \ No newline at end of file diff --git a/docs/multi_2/subpage_1.md b/docs/multi_2/subpage_1.md deleted file mode 100644 index 606dd7d..0000000 --- a/docs/multi_2/subpage_1.md +++ /dev/null @@ -1,16 +0,0 @@ -This is another way of doing subpages. Reference the yml file. - -## Information -Here is some course content. - - - -## Further reading -
- -- :fontawesome-solid-book-open:{ .lg .middle } [__CI/CD - Pre-commit resources__](../resources/references.md#pre-commit) - - --- - Information on GitHub Actions, Black, Flake8, Mypy, Isort, and Git Hooks - -
\ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 0abbd81..3ff190f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,6 +1,6 @@ -site_name: SITE NAME -repo_url: https://github.com/acceleratescience/REPO-TITLE -site_url: https://acceleratescience.github.io/REPO-TITLE/ +site_name: Introduction to diffusion models in generative AI +repo_url: https://github.com/acceleratescience/diffusion-models +site_url: https://acceleratescience.github.io/diffusion-models/ nav: - Home: - Welcome!: index.md @@ -10,10 +10,10 @@ nav: - Multi Page 1: - Subpage 1: multi_1/subpage_1.md - Subpage 2: multi_1/subpage_2.md - - Multi Page 2: - - multi_2/index.md - - Page 1: multi_2/subpage_1.md - - Page 2: multi_2/subpage_2.md + - Hugging Face Diffusers: + - hf_diffusers/index.md + - Image Generation: hf_diffusers/hf_mnist_gen.md + - ECG Generation: hf_diffusers/hf_ecg_gen.md - Resources: - resources/index.md - Slides: resources/slides.md