uploaded all project files
Browse files- .gitattributes +1 -0
- README.md +82 -0
- beamInference.py +71 -0
- beam_diffusion.py +65 -0
- datasets/DIYs.json +173 -0
- datasets/VIST.json +512 -0
- datasets/recipes.json +471 -0
- example.png +3 -0
- models/CoSeD/checkpoints/epoch=19-step=140.ckpt +3 -0
- models/CoSeD/cross_attention.py +26 -0
- models/CoSeD/sequence_predictor.py +675 -0
- models/clip/clip.py +65 -0
- models/diffusionModel/Latents_Singleton.py +30 -0
- models/diffusionModel/StableDiffusion.py +38 -0
- models/diffusionModel/configs/config_loader.py +34 -0
- models/diffusionModel/configs/diffusionModel.yml +6 -0
- tree/node.py +59 -0
- tree/tree.py +84 -0
- utils/utils.py +42 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
example.png filter=lfs diff=lfs merge=lfs -text
|
README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
language:
|
| 3 |
+
- en
|
| 4 |
+
base_model:
|
| 5 |
+
- stabilityai/stable-diffusion-2-1
|
| 6 |
+
tags:
|
| 7 |
+
- Beam-Search
|
| 8 |
+
- stable-diffusion
|
| 9 |
+
- Diffusers
|
| 10 |
+
- Latent-Space
|
| 11 |
+
pipeline_tag: text-to-image
|
| 12 |
+
---
|
| 13 |
+
# BeamDiffusion: Latent Beam Diffusion Models for Decoding Image Sequences
|
| 14 |
+
**BeamDiffusion** introduces a novel approach for generating coherent image sequences from text prompts by employing beam search in latent space. Unlike traditional methods that generate images independently, BeamDiffusion iteratively explores latent representations, ensuring smooth transitions and visual continuity across frames. A cross-attention mechanism efficiently scores and prunes search paths, optimizing both textual alignment and visual coherence.
|
| 15 |
+
BeamDiffusion addresses the challenge of maintaining visual consistency in image sequences generated from text prompts. By leveraging a beam search strategy in the latent space, it refines the generation process to produce sequences with enhanced coherence and alignment with textual descriptions, as outlined in the [paper](https://arxiv.org/abs/2503.20429).
|
| 16 |
+
|
| 17 |
+
## Quickstart Guide
|
| 18 |
+
|
| 19 |
+
Here's a basic example of how to use BeamDiffusion with the `transformers` library to generate an image sequence based on a series of text prompts:
|
| 20 |
+
|
| 21 |
+
```python
|
| 22 |
+
from huggingface_hub import snapshot_download
|
| 23 |
+
# Download the model snapshot
|
| 24 |
+
snapshot_download(repo_id="Gui28F/BeamDiffusion", local_dir="BeamDiffusionModel")
|
| 25 |
+
from BeamDiffusionModel.beam_diffusion import BeamDiffusionPipeline, BeamDiffusionConfig,BeamDiffusionModel
|
| 26 |
+
|
| 27 |
+
# Initialize the configuration, model, and pipeline
|
| 28 |
+
config = BeamDiffusionConfig()
|
| 29 |
+
model = BeamDiffusionModel(config)
|
| 30 |
+
pipe = BeamDiffusionPipeline(model)
|
| 31 |
+
|
| 32 |
+
# Define the input parameters
|
| 33 |
+
input_data = {
|
| 34 |
+
"steps": ["A lively outdoor celebration with guests gathered around, everyone excited to support the event.",
|
| 35 |
+
"A chef in a cooking uniform raises one hand dramatically, signaling it's time to serve the food.",
|
| 36 |
+
"Guests chat and laugh in a vibrant setting, with people gathered around tables, enjoying the event."],
|
| 37 |
+
"latents_idx": [0, 1, 2, 3],
|
| 38 |
+
"n_seeds": 4,
|
| 39 |
+
"steps_back": 2,
|
| 40 |
+
"beam_width": 2,
|
| 41 |
+
"window_size": 2,
|
| 42 |
+
"use_rand": True
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
# Generate the sequence of images
|
| 46 |
+
sequence_imgs = pipe(input_data)
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
**Result:**
|
| 50 |
+
|
| 51 |
+

|
| 52 |
+
|
| 53 |
+
## Input Parameters Explained
|
| 54 |
+
|
| 55 |
+
- **`steps`** (`list of strings`): Descriptions for each step in the image generation process. The model generates one image per step, forming a sequence that aligns with these descriptions.
|
| 56 |
+
|
| 57 |
+
- **`latents_idx`** (`list of integers`): Indices referring to specific positions in the latent space to be used during image generation. This allows the model to leverage different latent representations for diverse outputs.
|
| 58 |
+
|
| 59 |
+
- **`n_seeds`** (`int`): Number of random seeds to use for the generation process. Each seed provides a different starting point for the randomness in the first step, influencing the diversity of generated sequences.
|
| 60 |
+
|
| 61 |
+
- **`seeds`** (`list of integers`): Specific seeds to use for the generation process. If provided, these seeds override the `n_seeds` parameter, allowing for controlled randomness.
|
| 62 |
+
|
| 63 |
+
- **`steps_back`** (`int`): Number of previous steps to consider during the beam search process. This parameter helps refine the current generation by incorporating information from earlier steps.
|
| 64 |
+
|
| 65 |
+
- **`beam_width`** (`int`): Number of candidate sequences to maintain during inference. Beam search evaluates multiple potential outputs and keeps the most probable ones based on the defined criteria.
|
| 66 |
+
|
| 67 |
+
- **`window_size`** (`int`): Size of the "window" for beam search pruning. Determines after how many steps pruning starts, helping the model focus on more probable options as the generation progresses.
|
| 68 |
+
|
| 69 |
+
- **`use_rand`** (`bool`): Flag to introduce randomness in the inference process. If set to `True`, the model generates more varied and creative results; if `False`, it produces more deterministic outputs.
|
| 70 |
+
|
| 71 |
+
## Citation
|
| 72 |
+
|
| 73 |
+
If you use BeamDiffusion in your research or projects, please cite the following paper:
|
| 74 |
+
|
| 75 |
+
```
|
| 76 |
+
@article{fernandes2025latent,
|
| 77 |
+
title={Latent Beam Diffusion Models for Decoding Image Sequences},
|
| 78 |
+
author={Fernandes, Guilherme and Ramos, Vasco and Cohen, Regev and Szpektor, Idan and Magalh{\~a}es, Jo{\~a}o},
|
| 79 |
+
journal={arXiv preprint arXiv:2503.20429},
|
| 80 |
+
year={2025}
|
| 81 |
+
}
|
| 82 |
+
```
|
beamInference.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import random
|
| 2 |
+
|
| 3 |
+
from BeamDiffusionModel.models.CoSeD.cross_attention import get_softmax
|
| 4 |
+
from BeamDiffusionModel.models.diffusionModel.configs.config_loader import CONFIG
|
| 5 |
+
from BeamDiffusionModel.tree.tree import BeamSearchTree
|
| 6 |
+
from BeamDiffusionModel.utils.utils import gen_img
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def set_softmax(nodes, softmax, n_latents, n_max_latents):
|
| 10 |
+
for node, softmax_value in zip(nodes, softmax):
|
| 11 |
+
node.set_softmax(softmax_value, n_latents, n_max_latents)
|
| 12 |
+
|
| 13 |
+
def beam_inference(steps, latents_idx, n_seeds= 1, seeds=[], steps_back=2, beam_width=4, window_size=2, use_rand=True):
|
| 14 |
+
while len(seeds) < n_seeds:
|
| 15 |
+
seeds.append(random.randint(0, 10**6))
|
| 16 |
+
captions = steps
|
| 17 |
+
tree = BeamSearchTree(steps_back,beam_width,latents_idx,len(captions))
|
| 18 |
+
nodes_to_explore = []
|
| 19 |
+
for i, caption in enumerate(captions):
|
| 20 |
+
if i == 0:
|
| 21 |
+
for seed in seeds:
|
| 22 |
+
latents, img = gen_img(caption, seed=seed)
|
| 23 |
+
new_node = tree.add_node(tree.root, caption, i + 1, "Rand Seed", "Rand Seed",
|
| 24 |
+
img, latents, None)
|
| 25 |
+
nodes_to_explore.append(new_node)
|
| 26 |
+
else:
|
| 27 |
+
next_nodes = []
|
| 28 |
+
for child, parent_node in enumerate(nodes_to_explore):
|
| 29 |
+
parent_childs = []
|
| 30 |
+
current_step_embeddings, current_image_embeddings = [], []
|
| 31 |
+
if use_rand:
|
| 32 |
+
seed = random.randint(0, 10 ** 6)
|
| 33 |
+
latents, img = gen_img(caption, seed=seed)
|
| 34 |
+
new_node = tree.add_node(parent_node, caption, i + 1, "Rand Seed", "Rand Seed",
|
| 35 |
+
img, latents, None)
|
| 36 |
+
parent_childs.append(new_node)
|
| 37 |
+
current_step_embedding, current_image_embedding = new_node.get_features()
|
| 38 |
+
current_step_embeddings.append(current_step_embedding)
|
| 39 |
+
current_image_embeddings.append(current_image_embedding)
|
| 40 |
+
|
| 41 |
+
ancestors = parent_node.get_ancestors(steps_back-1)
|
| 42 |
+
|
| 43 |
+
for ancestor_idx, ancestor in enumerate(ancestors):
|
| 44 |
+
for latent in latents_idx:
|
| 45 |
+
ancestor_latent = ancestor.get_latent(latent)
|
| 46 |
+
latents, img = gen_img(caption, latent=ancestor_latent)
|
| 47 |
+
new_node = tree.add_node(parent_node, caption, i + 1, ancestor.step, latent,img, latents, None)
|
| 48 |
+
parent_childs.append(new_node)
|
| 49 |
+
current_step_embedding, current_image_embedding = new_node.get_features()
|
| 50 |
+
current_step_embeddings.append(current_step_embedding)
|
| 51 |
+
current_image_embeddings.append(current_image_embedding)
|
| 52 |
+
|
| 53 |
+
if current_step_embeddings != []:
|
| 54 |
+
previous_steps_embeddings, previous_images_embeddings = tree.get_previous_steps_features(parent_childs[-1])
|
| 55 |
+
softmax = get_softmax(previous_steps_embeddings, previous_images_embeddings,
|
| 56 |
+
current_step_embeddings,
|
| 57 |
+
current_image_embeddings)
|
| 58 |
+
set_softmax(parent_childs, softmax, len(latents_idx), CONFIG["stable_diffusion"]["diffusion_settings"]["steps"])
|
| 59 |
+
next_nodes += parent_childs
|
| 60 |
+
|
| 61 |
+
if i >= window_size:
|
| 62 |
+
print("-----------------------------------Cleaning some nodes-----------------------------------")
|
| 63 |
+
best_paths = tree.get_n_best_paths(beam_width, i + 1)
|
| 64 |
+
new_next_nodes = []
|
| 65 |
+
for node in next_nodes:
|
| 66 |
+
for node_path in best_paths:
|
| 67 |
+
if node in node_path:
|
| 68 |
+
new_next_nodes.append(node)
|
| 69 |
+
next_nodes = new_next_nodes
|
| 70 |
+
nodes_to_explore = next_nodes
|
| 71 |
+
return tree.best_path_imgs()
|
beam_diffusion.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import PretrainedConfig, PreTrainedModel, Pipeline
|
| 2 |
+
import torch
|
| 3 |
+
|
| 4 |
+
from BeamDiffusionModel.beamInference import beam_inference
|
| 5 |
+
# Your custom configuration for the BeamDiffusion model
|
| 6 |
+
class BeamDiffusionConfig(PretrainedConfig):
|
| 7 |
+
model_type = "beam_diffusion"
|
| 8 |
+
def __init__(self, latents_idx=None, n_seeds=4, seeds=None, steps_back=2, beam_width=4, window_size=2, use_rand=True, **kwargs):
|
| 9 |
+
super().__init__(**kwargs)
|
| 10 |
+
self.latents_idx = latents_idx if latents_idx else [0, 1, 2, 3]
|
| 11 |
+
self.n_seeds = n_seeds
|
| 12 |
+
self.seeds = seeds if seeds else []
|
| 13 |
+
self.steps_back = steps_back
|
| 14 |
+
self.beam_width = beam_width
|
| 15 |
+
self.window_size = window_size
|
| 16 |
+
self.use_rand = use_rand
|
| 17 |
+
|
| 18 |
+
import torch.nn as nn
|
| 19 |
+
from huggingface_hub import ModelHubMixin
|
| 20 |
+
# Custom BeamDiffusionModel that performs inference for each step
|
| 21 |
+
class BeamDiffusionModel(PreTrainedModel, ModelHubMixin):
|
| 22 |
+
config_class = BeamDiffusionConfig
|
| 23 |
+
model_type = "beam_diffusion"
|
| 24 |
+
|
| 25 |
+
def __init__(self, config):
|
| 26 |
+
super().__init__(config)
|
| 27 |
+
self.config = config
|
| 28 |
+
self.dummy_param = nn.Parameter(torch.zeros(1)) # Ensure at least one parameter
|
| 29 |
+
|
| 30 |
+
def forward(self, input_data):
|
| 31 |
+
images = beam_inference(
|
| 32 |
+
steps=input_data.get('steps', []),
|
| 33 |
+
latents_idx=input_data.get("latents_idx", [0, 1, 2, 3]),
|
| 34 |
+
n_seeds=input_data.get("n_seeds", 4),
|
| 35 |
+
seeds=input_data.get("seeds", []),
|
| 36 |
+
steps_back=input_data.get("steps_back", 2),
|
| 37 |
+
beam_width=input_data.get("beam_width", 4),
|
| 38 |
+
window_size=input_data.get("window_size", 2),
|
| 39 |
+
use_rand=input_data.get("use_rand", True)
|
| 40 |
+
)
|
| 41 |
+
return {"images": images}
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
# Custom pipeline to handle inference
|
| 45 |
+
class BeamDiffusionPipeline(Pipeline, ModelHubMixin):
|
| 46 |
+
def __init__(self, model, tokenizer=None, device="cuda", framework="pt"):
|
| 47 |
+
super().__init__(model=model, tokenizer=tokenizer, device=device, framework=framework)
|
| 48 |
+
|
| 49 |
+
def __call__(self, inputs):
|
| 50 |
+
return self._forward(inputs)
|
| 51 |
+
|
| 52 |
+
def preprocess(self, inputs):
|
| 53 |
+
"""Converts raw input data into model-ready format."""
|
| 54 |
+
return inputs # Keep as-is
|
| 55 |
+
|
| 56 |
+
def postprocess(self, model_outputs):
|
| 57 |
+
"""Processes model output into a user-friendly format."""
|
| 58 |
+
return model_outputs["images"] # Ensure this matches expected output
|
| 59 |
+
|
| 60 |
+
def _sanitize_parameters(self, **kwargs):
|
| 61 |
+
"""Handles unused parameters gracefully."""
|
| 62 |
+
return {}, {}, {}
|
| 63 |
+
|
| 64 |
+
def _forward(self, model_inputs):
|
| 65 |
+
return self.model(model_inputs)
|
datasets/DIYs.json
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"0": {
|
| 3 |
+
"title": "How to Clean a Sharpening Stone",
|
| 4 |
+
"steps": [
|
| 5 |
+
"Rub a quarter-size amount of honing oil onto your stone. Honing oil is a mineral oil that is commonly used in machine shops to carry away metal flecks from stone. Apply honing oil to your sharpening stone with your finger or a soft toothbrush in small, circular motions. Continue rubbing until you see metal flecks rise up from the pores of the stone.\nHoning oil can also be used to provide lubrication during the sharpening process.\nPurchase honing oil in hardware stores or online.\nUse honing oil to flush out your sharpening stone whenever you see metal flecks embedded in the surface, as they may reduce its effectiveness.",
|
| 6 |
+
"Wipe away the metal flecks with a damp cloth or paper towel. Wet a clean cloth or paper towel and wring it out. Gently wipe the surface of the sharpening stone with it. Be sure to remove all the metal filings that emerged from the stone.",
|
| 7 |
+
"Rinse the stone thoroughly under running water and dry it. Washing the sharpening stone will remove any remaining metal filings and debris from your stone. Run the stone under warm water for 1-2 minutes to ensure that it is clean. Dry the stone with a clean, dry cloth or paper towel. \nDo not use soap or anything other than water to clean it."
|
| 8 |
+
],
|
| 9 |
+
"captions": [
|
| 10 |
+
"A sharpening stone with a small pool of honing oil on its surface.",
|
| 11 |
+
"A hand holding a damp cloth wiping the surface of a sharpening stone. Metal flecks are visible on the damp cloth.",
|
| 12 |
+
"A sharpening stone being rinsed under running water."
|
| 13 |
+
]
|
| 14 |
+
},
|
| 15 |
+
"1": {
|
| 16 |
+
"title": "How to Clean Silk Rugs",
|
| 17 |
+
"steps": [
|
| 18 |
+
"Vacuum silk rugs regularly. Use a brushless suction head to vacuum silk rugs. Beater or roller brushes may pull out fibers, reduce the pile and damage the rug.",
|
| 19 |
+
"Sweep silk rugs with a broom. Gently sweep the rug to avoid damaging the fibers."
|
| 20 |
+
],
|
| 21 |
+
"captions": [
|
| 22 |
+
"A person using a vacuum cleaner on a silk rug.",
|
| 23 |
+
"A person sweeping a silk rug with a broom."
|
| 24 |
+
]
|
| 25 |
+
},
|
| 26 |
+
"2": {
|
| 27 |
+
"title": "How to Preserve Basil",
|
| 28 |
+
"steps": [
|
| 29 |
+
"Clean the basil leaves and allow to dry.",
|
| 30 |
+
"Place in a suitable storage container.",
|
| 31 |
+
"Sprinkle with salt. Shake through to cover in salt.",
|
| 32 |
+
"Fill the container with olive oil.",
|
| 33 |
+
"Cover the container. Place in the fridge and leave. Stored in this manner, the basil leaves will remain in great condition for use over the coming months.",
|
| 34 |
+
"Use as usual according to your recipe. Both the leaves and the oil (now infused with basil) can be used for cooking."
|
| 35 |
+
],
|
| 36 |
+
"captions": [
|
| 37 |
+
"Basil leaves being washed and dried.",
|
| 38 |
+
"A storage container filled with basil leaves.",
|
| 39 |
+
"A storage container filled with basil leaves being sprinkled with salt.",
|
| 40 |
+
"A storage container with basil leaves being filled with olive oil.",
|
| 41 |
+
"A storage container with basil leaves in the fridge.",
|
| 42 |
+
"A pan with chicken and basil leaves being cooked."
|
| 43 |
+
]
|
| 44 |
+
},
|
| 45 |
+
"3": {
|
| 46 |
+
"title": "How to Steam Clean Carpet",
|
| 47 |
+
"steps": [
|
| 48 |
+
"Remove everything from the room. Steam cleaning is most effective when you remove all toys, papers, and general clutter from the floor. Move all tables, chairs, and furniture out of the room. Clear as much of the floor space as you can.\nIf some furniture is too heavy to move, place squares of wax paper, foil, wood blocks, or plastic film under the legs to protect them from the moisture of the steam cleaner. You can\u2019t clean the carpet completely if you leave furniture in the room.\nIf you don\u2019t have room to move the furniture to another room, move it all to half of the room and do the room in two separate sections. Let the carpet dry before you move furniture back to the already cleaned half.",
|
| 49 |
+
"Dust the baseboards. As you run the steam cleaner, you might knock dust off the baseboards if you don\u2019t dust them beforehand. Use a dust cloth with wood polish or a long handled duster to remove as much of the dust as you can.\nDust ceiling fans and corners of the ceiling to prevent extra dust from falling on the carpet after you have steam cleaned them.",
|
| 50 |
+
"Vacuum the entire carpet carefully. Steam cleaners are meant to pull up small dirt particles that are down in the fibers of the carpet. They are not for removing hair and larger dirt pieces. Vacuum the entire room more slowly than you usually would. It is best to go over the room twice to get as much of the larger debris as possible. The second time, go over the room in the opposite direction to pick up more dirt.\nFor extra cleaning, use a nozzle attachment to get right up to the baseboards and edges of the room.\nVacuuming also fluffs up the carpet so that the steamer can clean the fibers more effectively.",
|
| 51 |
+
"Use stain remover on specific bad spots. Steamers can\u2019t always lift deep, set-in stains, so it\u2019s always helpful to treat stains before steaming the carpet. Use a carpet stain remover, or other natural solutions if you prefer. Blot the stain remover up with a cloth or leave it to be sucked up by the machine.\nWhen you do this, dab at the stains with a cloth. Never scrub at stains as this can cause them to work deeper into the carpet."
|
| 52 |
+
],
|
| 53 |
+
"captions": [
|
| 54 |
+
"A room with all furniture removed.",
|
| 55 |
+
"A person dusting the baseboards.",
|
| 56 |
+
"A person vacuuming a carpet.",
|
| 57 |
+
"A person using a stain remover on a carpet."
|
| 58 |
+
]
|
| 59 |
+
},
|
| 60 |
+
"4": {
|
| 61 |
+
"title": "How to Polish Wood",
|
| 62 |
+
"steps": [
|
| 63 |
+
"Wipe down your furniture with the wax remover. Dampen your dry microfiber cloth with the wax remover and wipe along the grain of the wood. Wait until it is completely dry to ensure that you won\u2019t damage the wood, then wipe off any excess dirt or wax with a dry microfiber cloth. Use 0000 steel wool to gently sand away any remaining marks or stains.\nIt is important to remove any excess wax buildup before polishing as any remaining wax will degrade your polish.\nTest your wax remover on an inconspicuous area before covering the entire piece of furniture.\nYou can purchase wax remover in any store, but you can also use a mixture of .5 cups (0.12\u00a0L) cups of water to .5 cups (0.12\u00a0L) of white vinegar if you would prefer a homemade option.",
|
| 64 |
+
"Apply thin layers of polish along the grain of the wood. Place a dry microfiber cloth on the open cap of polish and flip. This will allow the polish to absorb into the cloth without applying so much that it will begin pooling on the furniture. Rub the cloth along the grain of the wood to work in the polish.\nYou can continue to apply layers depending on how dry the furniture is and the level of shine you would like to achieve.\nMake sure to get in all crevices and corners. Open cabinets or drawers to polish the joints and interior spaces.\nBe sure to test the polish in an inconspicuous area before covering the entire piece of furniture.",
|
| 65 |
+
"Repeat the polishing process as needed. Once complete, your furniture should be glossy and shiny, but you can continue adding layers to achieve the finish you want. You can repeat the polishing process on a routine basis to keep your furniture looking great, but unless you apply a new layer of wax you won\u2019t need to use wax remover again."
|
| 66 |
+
],
|
| 67 |
+
"captions": [
|
| 68 |
+
"A person wiping down a piece of wood furniture with a wax remover.",
|
| 69 |
+
"A person applying polish to a piece of wood furniture.",
|
| 70 |
+
"A person polishing a piece of wood furniture."
|
| 71 |
+
]
|
| 72 |
+
},
|
| 73 |
+
"5": {
|
| 74 |
+
"title": "How to Make a Door",
|
| 75 |
+
"steps": [
|
| 76 |
+
"Measure the doorway where you\u2019ll be installing your door. Before you get to sawing, gluing, and sanding, you\u2019ll need to know exactly how big your door needs to be. Find the height and width of your empty doorway by running a tape measure down one side, then stretching it across the top. Make sure you jot your measurements down. You\u2019ll need to refer back to them later while you\u2019re cutting the panel for your door.",
|
| 77 |
+
"Acquire a 4 ft (1.2 m) x 8 ft (2.4 m) sheet of 1\u20442 in (1.3 cm) plywood. Run down to your local hardware store or home improvement center and purchase a sheet of plywood to use as the main panel for your new door. For a standard interior door, 1\u20442 in (1.3 cm) plywood will work best. A solid piece of plywood will create a door with a much sturdier construction than the hollow-bodied variety installed in most homes.",
|
| 78 |
+
"Mark the doorway dimensions on your plywood sheet with a pencil. Using the measurements you recorded earlier, draw one line down the length of the plywood corresponding to the height of the doorway and another line across the top to indicate the width. This will create a rough outline for your door panel. Use a ruler or straight edge to confirm that your lines are straight and precise. Otherwise, you could end up with a door that doesn\u2019t fit!",
|
| 79 |
+
"Cut the plywood to the correct dimensions using a circular saw. Guide the saw blade slowly over the plywood sheet along the height and width lines you just drew to trim the excess material from the edges. Depending on how your work bench is set up, you\u2019ll need to reposition either the plywood or the saw when it comes time to make your second cut. Laying a separate piece of lumber along your measurement lines will ensure cleaner cuts and help prevent mistakes. The standard size of an interior door is 80 inches (200 cm) x 24\u201330 inches (61\u201376 cm).",
|
| 80 |
+
"Sand the entire door panel. Run an electric sander or sheet of high-grit sandpaper over both sides of the panel, using even pressure to ensure that the outer surface is smooth and level. Once you\u2019ve sanded both faces, turn your attention to the edges of the panel. You may have to clamp or brace the panel against another object to hold it steady while you sand the edges. At this point, you can either move on to painting and installing the mounting hardware if you\u2019re satisfied with a plain, flat door, or cut a few more pieces of plywood to add textural accents to your blank panel."
|
| 81 |
+
],
|
| 82 |
+
"captions": [
|
| 83 |
+
"A person holding a tape measure against an empty doorway. Numbers are visible on the tape measure.",
|
| 84 |
+
"A stack of plywood sheets at a hardware store with a person reaching for one.",
|
| 85 |
+
"A sheet of plywood lying flat with a pencil and ruler beside it. Two straight lines are drawn on the plywood with measurement markings next to them.",
|
| 86 |
+
"A person using a circular saw to cut along a marked line on a sheet of plywood. Sparks are flying from the saw blade. A straight piece of lumber is positioned next to the cut line as a guide.",
|
| 87 |
+
"A person using an electric sander on a flat plywood door panel. Dust is visible in the air."
|
| 88 |
+
]
|
| 89 |
+
},
|
| 90 |
+
"6": {
|
| 91 |
+
"title": "How to Clean Natural Stone",
|
| 92 |
+
"steps": [
|
| 93 |
+
"Sweep off surface debris. If you are cleaning a natural stone floor, you'll want to use a fluffy mop or brush that has soft, natural bristles. This will prevent the stone from getting scratched by brushes with abrasive bristles. If you are cleaning natural stone countertops, a clean cotton rag or a handheld duster can remove surface debris. Sweep all the dirt and dust into a dustpan and dispose of it.\nIf you are cleaning natural stone floors, you can also use a vacuum.\nSweep or dust your natural stone at least twice a week.",
|
| 94 |
+
"Mix warm water and a mild dish detergent in a bucket. Fill up a bucket with five cups (1.1 l) of warm water from your faucet and put two to three drops of a mild, pH neutral dish soap into the bucket. Mix the water and soap together until bubbles start to form on the top. Read the label of the dish soap that you are purchasing to make sure that it doesn't contain any acid, which could damage the natural stone.\nAlcohol, citrus, and vinegar all contain acids that are corrosive to natural stone.\nYou can also ask a stone retailer to direct you towards a stone-specific cleaner.",
|
| 95 |
+
"Wipe down the natural stone with the solution. Use a soft mop or a rag and dip it into the solution that you just created. Work in circular motions to lift up any stuck on soap scum, dirt, or gunk that is on your stone. If you are using a mop, go left and right in large sweeping motions to remove dirt and gunk from the floor.",
|
| 96 |
+
"Rinse off the solution with distilled water. Rinse the stone with distilled water until there is no more soap or cleaning solution left on the stone. Regular water from your tap may contain minerals that could discolor the stone. The cleaner can also be absorbed by the stone and cause discoloration, so make sure that you rinse it thoroughly.\nIf you don't have distilled water, you can boil tap water instead.",
|
| 97 |
+
"Dry the stone. Dry the stone with a soft, synthetic or cotton rag until all of the moisture is gone. Do not leave any cleaner or liquid on the surface of the stone. Continue to buff the area until your natural stone looks shiny and clean."
|
| 98 |
+
],
|
| 99 |
+
"captions": [
|
| 100 |
+
"A person using a soft-bristled mop to sweep dust and debris off a natural stone floor.",
|
| 101 |
+
"A bucket filled with warm water and a few drops of dish soap. Bubbles are visible on the water's surface.",
|
| 102 |
+
"A person using a soft cloth dipped in cleaning solution to wipe a natural stone countertop in circular motions.",
|
| 103 |
+
"A person pouring distilled water from a watering can onto a natural stone surface.",
|
| 104 |
+
"A person buffing a natural stone surface with a dry, clean cloth."
|
| 105 |
+
]
|
| 106 |
+
},
|
| 107 |
+
"7": {
|
| 108 |
+
"title": "How to Frame an Oil Painting",
|
| 109 |
+
"steps": [
|
| 110 |
+
"Select a floating or baguette frame for a minimalistic, modern look. Baguette frames refer to flat panels of wood or metal that fit along the edges of your painting without obscuring any portion of the image. Float frames use a mat to set your image inside a simple frame. These frames provide a modern look, and differ from traditional frames by adding very little visual impact on their own. They look sort of like siding or open borders for a piece of art.\nFloat and baguette frames tend to emphasize the work itself, since the frames tend to contain few details on their own.\nFloat frames can make a work appear more striking. The mat helps isolate the work in the center of the wall, making it stand out more.\nBaguette frames can make a work look dramatic. The minimalistic frame lifts the image off of the wall a few inches, which can make it seem like the work is literally popping out.\nThe difference between a baguette and float frame is whether there is any space between the canvas and the frame itself. Float frames have a space, which is sometimes filled in with a mat, while baguette frames leave no room between the frame and the painting.",
|
| 111 |
+
"Use a traditional frame for classic landscapes and portraits. Traditional frames come in all types of shapes, sizes, and designs. They tend to be metal or wood, and add an additional visual element to a painting\u2019s presentation. Choose a frame that you think works well alongside your image without drawing the viewer\u2019s attention away from what\u2019s important.\nTraditional frames cover the edges of a canvas. They also tend to have minor details and patterns built into the frame. These minor elements change the way that a viewer perceives a work.\nWhen in doubt, opt for a simpler traditional frame. You can always upgrade the frame later when you need a change of pace.",
|
| 112 |
+
"Get an antique frame for high-end or older oil paintings. For older works or paintings with a high price tag, choose an antique frame to really make your work stand out. Antique frames tend to have high levels of detail and create a striking impression on their own, which can demand attention as soon as the viewer enters the room.\nAntique frames tend to be have expressive designs and strange colors. These can help stress the specialness of a historical or expensive piece of art.\nLook for antique frames at antique shops.",
|
| 113 |
+
"Display your art without a frame if the sides of the canvas are painted. If the canvas comes with a prebuilt frame and the artist elected to paint details along the sides of the canvas, you probably don\u2019t need a frame. The artist made a conscious decision to extend the image past the edge of the canvas, and covering it could reduce the impact of an image.\nYou can tell if a framed canvas was meant to be hung on its own if the artist installed hangers along the backside of the frame."
|
| 114 |
+
],
|
| 115 |
+
"captions": [
|
| 116 |
+
"A modern oil painting with a float frame. A thin border surrounds the painting, creating a clean and contemporary look.",
|
| 117 |
+
"A traditional oil painting (e.g., landscape or portrait) with a decorative wooden frame. The frame complements the artwork's style without overwhelming it.",
|
| 118 |
+
"An antique oil painting with an ornate frame. The frame features rich details and flourishes, enhancing the prestige of the artwork.",
|
| 119 |
+
"A close-up of a painted canvas edge. The sides of the canvas continue the artwork, creating a seamless flow from the front."
|
| 120 |
+
]
|
| 121 |
+
},
|
| 122 |
+
"8": {
|
| 123 |
+
"title": "How to Remove Oil Stains from Paper",
|
| 124 |
+
"steps": [
|
| 125 |
+
"Create a cleaning solution with half plain water, half white vinegar. Combine 1\u20442\u00a0\u00a0c (120\u00a0ml) of white vinegar and 1\u20442\u00a0\u00a0c (120\u00a0ml) of plain water in a cup or bowl. Set your solution aside for now until you are ready to clean.\nVinegar is a natural cleaner that works like a mild bleach and can be used to clean many types of materials.",
|
| 126 |
+
"Lay the affected piece of paper out flat on a hard, waterproof surface. Flatten it out as much as possible. You can place heavy objects on the corners to stretch it out and keep it flat and stable.\nRemember that the sooner you start working on the oil stain, the easier it will be to remove.",
|
| 127 |
+
"Moisten a cotton ball or swab with the cleaning solution and clean the spot. Gently and carefully dab the oil stain with the moistened cotton ball or swab. Be careful not to use too much of the cleaning solution as you could damage the paper you are cleaning if it gets too wet.\nIf the oil spot looks like it is getting too wet, dab it dry with a paper towel or let it air dry so that you don\u2019t create a hole in the paper.\nKeep dabbing rather than letting the vinegar soak in, until the stain appears to be lifted, then you can dry the area.",
|
| 128 |
+
"Dry the cleaned area by dabbing it with a dry paper towel and letting it air dry. Once the spot is completely dry you can see if the stain was completely removed. If there is still an oil stain, repeat the process to remove as much of it as possible.\nKeep in mind that this method will work better the fresher the stain is, older stains may not come out completely but you can reduce their visibility."
|
| 129 |
+
],
|
| 130 |
+
"captions": [
|
| 131 |
+
"A cup with equal parts white vinegar and water.",
|
| 132 |
+
"A piece of paper with an oil stain laid out flat on a table.",
|
| 133 |
+
"A person using a cotton swab to dab a cleaning solution onto an oil stain on a piece of paper.",
|
| 134 |
+
"A person drying a cleaned oil stain on a piece of paper with a paper towel."
|
| 135 |
+
]
|
| 136 |
+
},
|
| 137 |
+
"9": {
|
| 138 |
+
"title": "How to Paint Plastic Models",
|
| 139 |
+
"steps": [
|
| 140 |
+
"Paint your base coats using as few strokes as possible. To start painting a smaller or intricate model, grab the color that you\u2019re going to use for the base of your model. Load your brush with your base color and wipe it back and forth on your easel or palette to remove the excess paint. Apply your base coat over the areas that you want to paint using as few strokes as possible. Hold your brush at a slight angle and make each brush stroke as large as you can without brushing a part of the model that you aren\u2019t trying to cover.\nFor larger surfaces, use a flat brush. The tip of the brush must be smaller than the surface that you\u2019re painting. For models smaller than 1 foot (30\u00a0cm), a 1\u20132\u00a0in (2.5\u20135.1\u00a0cm) brush is appropriate. The size of the brush is largely a matter of personal preference, though.\nIf your base coat is a lighter color, feel free to paint the entire model. The other paints will easily cover the surfaces you\u2019ve painted. If the base coat is a darker color, like a black or blue, try to avoid painting other surfaces of the model. It will take multiple coats to cover a darker base coat.\nTo figure out what your base coat\u2019s color is, determine what color will cover the highest percentage of your model\u2019s surface. This is the color of your base coat.\nSome models have instructions for which colors you should use, but you can always pick your colors out yourself. There are no right or wrong choices when it comes to picking colors. It\u2019s totally up to you!",
|
| 141 |
+
"Overlap your brush strokes to ensure an even coat of color. When painting your model, overlap each brush stroke to avoid leaving gaps between them. If you try to place each brush stroke perfectly against one another, you\u2019ll naturally miss small areas in between the paint strokes. Overlap each stroke to ensure that your colors come out evenly.\nThis will also prevent smearing, since you\u2019ll be spreading the paint out before it has an opportunity to start drying. If you have to go in and add paint to spaces that you\u2019ve missed, you\u2019ll have to wait for the coat to dry entirely before you can add more color.",
|
| 142 |
+
"Wait 24-72 hours in between coats to let them dry. After you finish your base coat, wait 24-72 hours to give the paint time to settle. Acrylic paint will dry closer to the 24-48 hour range, while enamel usually takes 48-72 hours to dry. The thickness of your coat will also impact the amount of time it takes for your paint to dry.\nIf you\u2019re trying to blend colors, feel free to continue painting while your paint is wet.",
|
| 143 |
+
"Work your way down to the smaller layers after painting the base coat. Once you finish your base coat, add your next biggest layer of color. Work from larger layers to smaller layers to avoid having to work around smaller brushstrokes. Use a smaller brush to cover smaller layers, and continue to use as few brush strokes as possible. Overlap each application of color to ensure that the coat comes out evenly.\nFor example, if you\u2019re painting a model police officer, your base layer is probably the blue uniform. The next biggest section of color will be the skin tone, followed by the silver buckle and buttons and the black details on the uniform.",
|
| 144 |
+
"Apply details with your thinner brushes by using short strokes. Once you\u2019ve added your key layers of paint, start adding your details. Use the thinnest brush that you have to carefully apply small lines, textures, or shadows. Use a short, flicking motion and only load the tip of your brush to avoid adding too much paint. Work slowly and be careful to avoid putting paint where it doesn\u2019t belong.\nFor some people, it\u2019s easier to keep their hand steady if they brace it on a table or small stack of books. Maintaining a steady hand is the best way to ensure that you don\u2019t miss a stroke.\nDon\u2019t be too hard on yourself. It can take a lot of practice to develop the skills required to paint small details. The more you practice though, the better you\u2019ll get at it.\nFor smaller miniatures, use a 0, 00, or 000 round brush. These brushes are smaller than 1\u204432\u00a0in (0.079\u00a0cm). For larger models, details may be painted with a 1 or 2 brush, which are only slightly larger than 1\u204432\u00a0in (0.079\u00a0cm).",
|
| 145 |
+
"Thin your paint before applying textures or translucent colors. If you want to add dirt, blood, dust, or some other texture, thin your paint before applying it. Acrylic paint is thinned with water, while enamel requires a special modelling solvent. Start with a drop or two of thinner when mixing your paint. Continue to add thinner until you\u2019ve achieved the opacity and look that you desire.\nTest your mixed paint on a blank sheet of paper to see how it looks. If you don\u2019t like the texture, add paint or thinner to change the opacity as desired.\nUse droppers to mix small amounts if you\u2019re painting a smaller model. You usually don\u2019t need more than a drop or two to adequately thin out paint for a texture.",
|
| 146 |
+
"Use a toothpick to carve grooves or add tiny details. For extremely intricate details, grab a toothpick with a sharp point. Use the toothpick to carefully remove small sections of paint and add details. You can also dip the tip of your toothpick into paint to apply small specks of color where you want them.\nIf you\u2019re trying to add shadows, use a cotton swab instead of a toothpick. This usually produces a shadowy effect without adding too much paint.",
|
| 147 |
+
"Clean your brushes as soon as you\u2019re done painting. When you\u2019ve finished painting, fill a cup with 2\u20133\u00a0in (5.1\u20137.6\u00a0cm) of your cleaning solution. Use water to clean your acrylic brushes and use paint thinner or enamel cleaner for enamel brushes. Wipe your bristles against the side of the cup repeatedly to remove the majority of the paint. Once most of the paint is gone, rinse your enamel or acrylic brushes under a stream of warm water.\nNever push your bristles directly into the bottom of the cup. This can damage your brushes by fraying the bristles.\nAfter you\u2019ve dried your brushes, you can rub petroleum jelly on the bristles to preserve them.\nIf you don\u2019t clean your brushes, you\u2019re going to waste a lot of money replacing them."
|
| 148 |
+
],
|
| 149 |
+
"captions": [
|
| 150 |
+
"A person holding a paintbrush at an angle, applying paint to a plastic model. The brush is loaded with a small amount of paint, and the person is using long strokes to cover a large area.",
|
| 151 |
+
"Close-up of a person painting a plastic model with a brush. The brush is overlapping the previous stroke slightly, ensuring there are no gaps between the painted areas.",
|
| 152 |
+
"A painted plastic model sitting on a table. A clock with an arrow pointing between 24 and 72 hours is next to the model.",
|
| 153 |
+
"A partially painted plastic model. The base coat is complete, and the person is now applying a different color to a larger section of the model.",
|
| 154 |
+
"A person carefully painting a small detail on a plastic model with a very thin brush. The person's other hand is braced on a stack of books for stability.",
|
| 155 |
+
"A palette with two drops of paint and a small amount of water mixed together. A paintbrush rests in the palette.",
|
| 156 |
+
"A person holding a toothpick and carefully scraping away a small section of paint on a plastic model to create a detail.",
|
| 157 |
+
"A cup filled with cleaning solution and a paintbrush being rinsed under warm water."
|
| 158 |
+
]
|
| 159 |
+
},
|
| 160 |
+
"10": {
|
| 161 |
+
"title": "Make a Decorative Jar",
|
| 162 |
+
"steps": [
|
| 163 |
+
"Take an empty glass jar.",
|
| 164 |
+
"Paint or decorate it with stickers, twine, or washi tape.",
|
| 165 |
+
"Use it as a vase, a pen holder, or a candle holder."
|
| 166 |
+
],
|
| 167 |
+
"captions": [
|
| 168 |
+
"A clean, empty glass jar with paint, stickers, twine, and other decorative supplies beside it.",
|
| 169 |
+
"A person painting the jar, wrapping twine around it, or applying stickers.",
|
| 170 |
+
"The finished decorative jar being used as a vase, pen holder, or candle holder."
|
| 171 |
+
]
|
| 172 |
+
}
|
| 173 |
+
}
|
datasets/VIST.json
ADDED
|
@@ -0,0 +1,512 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"0": {
|
| 3 |
+
"title": "Fireworks - 4th July in Washington, DC",
|
| 4 |
+
"steps": [
|
| 5 |
+
"The two friends went to a new location",
|
| 6 |
+
"Large crowds had gathered on the steps of the Lincoln Memorial",
|
| 7 |
+
"We had our own little spot on the grass. ",
|
| 8 |
+
"As the evening grew darker the crowd was gearing up to enjoy the show, with a great view of the Washington Monument.",
|
| 9 |
+
"The fireworks were the best that we had ever seen"
|
| 10 |
+
],
|
| 11 |
+
"captions": [
|
| 12 |
+
"Two friends walk through a busy area, making their way toward the Lincoln Memorial on a bright day.",
|
| 13 |
+
"A large crowd sits and stands on the steps of the Lincoln Memorial, engaged in conversation and waiting for the event.",
|
| 14 |
+
"Two friends sit on the grass among many others, settling into their spot for the evening.",
|
| 15 |
+
"As the sky darkens, people sit facing the Washington Monument, eagerly awaiting the show.",
|
| 16 |
+
"Fireworks light up the night sky, reflecting over the Washington Monument as the crowd watches in awe."
|
| 17 |
+
]
|
| 18 |
+
},
|
| 19 |
+
"1": {
|
| 20 |
+
"title": "Klamath Project Construction",
|
| 21 |
+
"steps": [
|
| 22 |
+
"it was a simpler time indeed ",
|
| 23 |
+
"We fired up the machinery and got to work.",
|
| 24 |
+
"We were building a new waterway for the reservoir to spill into.",
|
| 25 |
+
"the men weeped as they buried their brothers",
|
| 26 |
+
"Finally, we added some chemicals to the new water filtration system."
|
| 27 |
+
],
|
| 28 |
+
"captions": [
|
| 29 |
+
"A flume stretches over a river, surrounded by scattered debris, capturing a moment of industrial progress.",
|
| 30 |
+
"Workers operate heavy machinery at an unfinished bridge construction site, dust rising as they labor.",
|
| 31 |
+
"Water rushes over the newly completed spillway of the Gerber Dam for the first time, marking a milestone.",
|
| 32 |
+
"A somber group of men stand by a freshly dug ditch, heads bowed as they pay tribute to their fallen comrades.",
|
| 33 |
+
"A man carefully pours liquid into a large gallon, finalizing the water filtration system with chemical treatment."
|
| 34 |
+
]
|
| 35 |
+
},
|
| 36 |
+
"2": {
|
| 37 |
+
"title": "Isfahan: 2nd Iranian flickr Gathering",
|
| 38 |
+
"steps": [
|
| 39 |
+
"It's nice to be able to look back and see how things are, how they were, and how they've changed to get here.",
|
| 40 |
+
"We visited many places, some so beautiful in very subtle ways.",
|
| 41 |
+
"He encountered many great people on his visit.",
|
| 42 |
+
"Afterwards, we met a nice woman who explained that she was much too shy to have her photo taken.",
|
| 43 |
+
"Heritage and history are important things to the world."
|
| 44 |
+
],
|
| 45 |
+
"captions": [
|
| 46 |
+
"A young boy stands confidently, looking at the camera as others around him reflect on their journey.",
|
| 47 |
+
"A softly lit scene showcases a historic church with its lights glowing, surrounded by a peaceful atmosphere.",
|
| 48 |
+
"A gathering of people is seen observing an important object, their faces filled with curiosity and admiration.",
|
| 49 |
+
"A woman in a headscarf stands slightly apart, gesturing gently with her hand while speaking to someone nearby.",
|
| 50 |
+
"A detailed mural filled with vivid imagery depicts a historical battle, capturing the essence of heritage and history."
|
| 51 |
+
]
|
| 52 |
+
},
|
| 53 |
+
"3": {
|
| 54 |
+
"title": "Yosemite Weekend",
|
| 55 |
+
"steps": [
|
| 56 |
+
"It was a beautiful day in the forest.",
|
| 57 |
+
"We were lucky enough to see some wildlife, like this deer.",
|
| 58 |
+
"I fed a squirrel and it seemed very hungry.",
|
| 59 |
+
"A snake came out of nowhere and scared me. ",
|
| 60 |
+
"The scenery from the top of the mountain was breathtaking. "
|
| 61 |
+
],
|
| 62 |
+
"captions": [
|
| 63 |
+
"Sunlight filters through towering trees, casting dappled shadows on the forest floor.",
|
| 64 |
+
"A deer stands cautiously in a forest clearing, ears perked up as it listens to the sounds around.",
|
| 65 |
+
"A plump squirrel eagerly nibbles on food, its tiny paws clutching a morsel.",
|
| 66 |
+
"A snake slithers out from beneath the undergrowth, its eyes fixed intently ahead.",
|
| 67 |
+
"From the mountain peak, the landscape unfolds into a vast, breathtaking view of valleys and waterfalls."
|
| 68 |
+
]
|
| 69 |
+
},
|
| 70 |
+
"4": {
|
| 71 |
+
"title": "4th of July 2006",
|
| 72 |
+
"steps": [
|
| 73 |
+
"This was the first time my sister saw my son. ",
|
| 74 |
+
"He seemed to like the company of his new relatives. ",
|
| 75 |
+
"The kids enjoyed their self and I am happy.",
|
| 76 |
+
"He couldn't walk, let alone jump but he was having a good time regardless. ",
|
| 77 |
+
"The loving man in our lives reminded us of the importance of family. "
|
| 78 |
+
],
|
| 79 |
+
"captions": [
|
| 80 |
+
"A woman arrives at a park with her baby, meeting her sister for the first time in a long while.",
|
| 81 |
+
"A baby sits on a picnic blanket, curiously observing his new relatives gathered around him.",
|
| 82 |
+
"Children laugh and play together on a bounce house, enjoying the family gathering.",
|
| 83 |
+
"A baby sits on the grass, unable to walk but joyfully clapping as the kids jump nearby.",
|
| 84 |
+
"A loving father embraces his family, reminding everyone of the warmth and bond they share."
|
| 85 |
+
]
|
| 86 |
+
},
|
| 87 |
+
"5": {
|
| 88 |
+
"title": "07.04.06 Fourth of July",
|
| 89 |
+
"steps": [
|
| 90 |
+
"Some are raised to believe that the world takes all kinds of people to make it go 'round. ",
|
| 91 |
+
"Our group of friends certainly demonstrates that adage to be true. ",
|
| 92 |
+
"There are always interesting moments to be found for those hanging around any of us.",
|
| 93 |
+
"Moments that you aren't quite sure what is going on, and aren't really sure you want to know either.",
|
| 94 |
+
"But everything is always in good fun, and we enjoy hanging out."
|
| 95 |
+
],
|
| 96 |
+
"captions": [
|
| 97 |
+
"A woman stands on a busy street corner, casually smoking as cars pass by.",
|
| 98 |
+
"A group of friends sits together under a patio umbrella, laughing and enjoying drinks.",
|
| 99 |
+
"A woman takes a bite of her frozen drink while chatting with her friends.",
|
| 100 |
+
"A man with food on his lips gestures animatedly, mid-conversation, as others react with amusement.",
|
| 101 |
+
"A few friends walk down a rainy street, still laughing and enjoying the night together."
|
| 102 |
+
]
|
| 103 |
+
},
|
| 104 |
+
"6": {
|
| 105 |
+
"title": "July4",
|
| 106 |
+
"steps": [
|
| 107 |
+
"There was a parade going on.",
|
| 108 |
+
"A another man saying a speech to the crowd.",
|
| 109 |
+
"Everyone looked like they were having fun. ",
|
| 110 |
+
"These kids were fighting over the flag but finally stopped. ",
|
| 111 |
+
"Later on that night there was fireworks! God bless America!"
|
| 112 |
+
],
|
| 113 |
+
"captions": [
|
| 114 |
+
"A patriotic parade moves down the street with men in red berets and white gloves carrying flags.",
|
| 115 |
+
"A man dressed in a Civil War uniform stands on a decorated float, addressing the excited crowd.",
|
| 116 |
+
"People of all ages line the streets, smiling and cheering as the parade continues.",
|
| 117 |
+
"Two kids stand in front of an American flag, their hands raised as they playfully argue over it.",
|
| 118 |
+
"As night falls, bright blue and yellow fireworks explode in the sky, marking the grand finale of the celebration."
|
| 119 |
+
]
|
| 120 |
+
},
|
| 121 |
+
"7": {
|
| 122 |
+
"title": "4th of July",
|
| 123 |
+
"steps": [
|
| 124 |
+
"The waiting was almost too much for the Kid Town citizens.",
|
| 125 |
+
"Of course, when evening came and my wife and I wanted to nap, the kids wanted to run around.",
|
| 126 |
+
"The kid's especially loved that they were able to use sparklers while they waited for the show.",
|
| 127 |
+
"Finally, everyone settled to watch the fireworks. ",
|
| 128 |
+
"The fireworks were fantastic."
|
| 129 |
+
],
|
| 130 |
+
"captions": [
|
| 131 |
+
"A lively town square filled with eager children and families waiting excitedly.",
|
| 132 |
+
"A couple sits on a bench, trying to rest as children run and play around them.",
|
| 133 |
+
"A young boy in a robe joyfully waves a sparkler, its glow illuminating his face.",
|
| 134 |
+
"Families and children lie on blankets, gazing up in anticipation of the fireworks.",
|
| 135 |
+
"Brilliant fireworks explode in the night sky, casting colorful light over the crowd."
|
| 136 |
+
]
|
| 137 |
+
},
|
| 138 |
+
"8": {
|
| 139 |
+
"title": "July 4th Barbecue - Technology Teams",
|
| 140 |
+
"steps": [
|
| 141 |
+
"Today is the big celebration and everyone is here to support.",
|
| 142 |
+
"The chef put his hand in the air, because it was time to surrender the food. He is so funny.",
|
| 143 |
+
"Nobody wanted to miss this wonderful event.",
|
| 144 |
+
"Cindi loved her boss's cooking but was especially fond of the strawberry dessert he made every year.",
|
| 145 |
+
"She got too much on her plate and fed some to a fellow coworker."
|
| 146 |
+
],
|
| 147 |
+
"captions": [
|
| 148 |
+
"A lively outdoor celebration with guests gathered around, everyone excited to support the event.",
|
| 149 |
+
"A chef in a cooking uniform raises one hand dramatically, signaling it's time to serve the food.",
|
| 150 |
+
"Guests chat and laugh in a vibrant setting, with people gathered around tables, enjoying the event.",
|
| 151 |
+
"A woman admires a beautiful strawberry dessert being served by her boss at the celebration.",
|
| 152 |
+
"A woman, smiling, offers a strawberry to a coworker sitting next to her, sharing the dessert."
|
| 153 |
+
]
|
| 154 |
+
},
|
| 155 |
+
"9": {
|
| 156 |
+
"title": "fourth of july",
|
| 157 |
+
"steps": [
|
| 158 |
+
"We look forward to the recycling parade every year. ",
|
| 159 |
+
"We pulled them along the road.",
|
| 160 |
+
"Others stand by and watch.",
|
| 161 |
+
"The race for the children at the end was so much fun!",
|
| 162 |
+
"Thankfully all the fun is kept safe by our local police force."
|
| 163 |
+
],
|
| 164 |
+
"captions": [
|
| 165 |
+
"A colorful recycling parade takes place on a lively residential street with families and children participating.",
|
| 166 |
+
"A decorated wagon rolls down the road, with a little girl smiling as she's pulled along by her parents.",
|
| 167 |
+
"A group of onlookers stand on the sidewalk, watching the parade with excitement and interest.",
|
| 168 |
+
"Children race joyfully at the end of the parade, their laughter and energy filling the air.",
|
| 169 |
+
"Local police officers on horseback ensure safety as they patrol the streets during the event."
|
| 170 |
+
]
|
| 171 |
+
},
|
| 172 |
+
"10": {
|
| 173 |
+
"title": "Independence Day Parade",
|
| 174 |
+
"steps": [
|
| 175 |
+
"The festival was a blast. ",
|
| 176 |
+
"It was quite a performance to watch.",
|
| 177 |
+
"then it started to get interesting and elaborate ",
|
| 178 |
+
"Horses were used for tricks,",
|
| 179 |
+
"Next came the old cars."
|
| 180 |
+
],
|
| 181 |
+
"captions": [
|
| 182 |
+
"A festival scene filled with people gathered around, enjoying the lively atmosphere.",
|
| 183 |
+
"A captivating performance unfolds with vibrant displays of skill and flair.",
|
| 184 |
+
"The excitement grows as the tricks become more elaborate, with horses performing intricate maneuvers.",
|
| 185 |
+
"A majestic horse prances gracefully as a rider performs impressive stunts.",
|
| 186 |
+
"An old car drives through the parade, commemorating fallen soldiers as spectators watch."
|
| 187 |
+
]
|
| 188 |
+
},
|
| 189 |
+
"11": {
|
| 190 |
+
"title": "Fourth of July, 2007",
|
| 191 |
+
"steps": [
|
| 192 |
+
"Today, there was a parade held out on the grounds.",
|
| 193 |
+
"There were all kinds of people there.",
|
| 194 |
+
"It's nice to see the participants enjoying themselves.",
|
| 195 |
+
"Next in line came the flag team.",
|
| 196 |
+
"Before long, it was already nighttime and we went home."
|
| 197 |
+
],
|
| 198 |
+
"captions": [
|
| 199 |
+
"Soldiers march in flawless formation, their uniforms sharp and the rhythm of their footsteps echoing through the streets.",
|
| 200 |
+
"The parade is alive with color, dancers and musicians filling the streets with joy and energy.",
|
| 201 |
+
"A flamenco dancer spins elegantly, her colorful dress flowing with every movement, captivating the onlookers.",
|
| 202 |
+
"A woman holds a red flag high, her face beaming with pride as her group marches past.",
|
| 203 |
+
"The vibrant city quiets as the day winds down, the lights dimming as the final notes of the parade fade away."
|
| 204 |
+
]
|
| 205 |
+
},
|
| 206 |
+
"12": {
|
| 207 |
+
"title": "Chapel Hill Fireworks",
|
| 208 |
+
"steps": [
|
| 209 |
+
"It was fourth of july night.",
|
| 210 |
+
"It was a sight to behold!",
|
| 211 |
+
"Some weren't as big or bright as others.",
|
| 212 |
+
"Everyone had a good time watching them.",
|
| 213 |
+
"The show was so much fun and I wish I could go again. "
|
| 214 |
+
],
|
| 215 |
+
"captions": [
|
| 216 |
+
"The streets are bathed in the warm glow of streetlights as the crowd eagerly awaits the fireworks display.",
|
| 217 |
+
"The night sky bursts with bright blue and white fireworks, sparkling in the cool evening air.",
|
| 218 |
+
"Explosions of red, green, and gold create intricate patterns as the fireworks explode high above.",
|
| 219 |
+
"Families stand together, faces illuminated by the glow of the fireworks, eyes wide in amazement.",
|
| 220 |
+
"The grand finale fills the sky with a cascade of dazzling lights, leaving the crowd in awe."
|
| 221 |
+
]
|
| 222 |
+
},
|
| 223 |
+
"13": {
|
| 224 |
+
"title": "4th of July, 2007, Breckenridge",
|
| 225 |
+
"steps": [
|
| 226 |
+
"The owner took a picture with the dog.",
|
| 227 |
+
"...and my husband!",
|
| 228 |
+
"And both know just how to get what they want.",
|
| 229 |
+
"The dog rolled around and enjoyed the heat.",
|
| 230 |
+
"And they are in no way spoiled....Um yeah...ok."
|
| 231 |
+
],
|
| 232 |
+
"captions": [
|
| 233 |
+
"A woman smiles brightly, cradling her furry companion in her arms, both basking in the sunlight.",
|
| 234 |
+
"A man sits leisurely on a park bench, his dog lying contentedly by his side, enjoying the serene day.",
|
| 235 |
+
"The woman carefully adjusts the straps on her dog's harness, ensuring comfort before they set off again.",
|
| 236 |
+
"A joyful black dog rolls around in the soft grass, soaking in the warm rays of the sun.",
|
| 237 |
+
"The two dogs lie peacefully together, curled up in a contented slumber, completely at ease."
|
| 238 |
+
]
|
| 239 |
+
},
|
| 240 |
+
"14": {
|
| 241 |
+
"title": "4th of July",
|
| 242 |
+
"steps": [
|
| 243 |
+
"Then multiple fireworks were let off at different times.",
|
| 244 |
+
"The fireworks were huge and we had a really great view of them.",
|
| 245 |
+
"The white fireworks were the most clear in the sky.",
|
| 246 |
+
"As the finale approached, more and more fireworks filled the sky.",
|
| 247 |
+
"I had a great time, the finale of the fireworks was awesome!"
|
| 248 |
+
],
|
| 249 |
+
"captions": [
|
| 250 |
+
"A series of fireworks light up the sky, each burst more brilliant than the last, as the crowd watches in awe.",
|
| 251 |
+
"Massive white fireworks explode against the dark canvas of the night, casting shimmering reflections on the ground below.",
|
| 252 |
+
"The sky is alight with a dazzling array of white fireworks, each explosion more stunning than the last.",
|
| 253 |
+
"The finale draws near, and the number of fireworks exploding in the sky intensifies, filling the crowd with excitement.",
|
| 254 |
+
"The grand finale is a riot of color, with fireworks bursting in every direction, leaving everyone stunned and delighted."
|
| 255 |
+
]
|
| 256 |
+
},
|
| 257 |
+
"15": {
|
| 258 |
+
"title": "Independance Day 2007",
|
| 259 |
+
"steps": [
|
| 260 |
+
"The fireworks begin to go off.",
|
| 261 |
+
"The explosions also got more complex.",
|
| 262 |
+
"Look at all of those fireworks!",
|
| 263 |
+
"It seemed much brighter up there, ",
|
| 264 |
+
"in the dark night sky."
|
| 265 |
+
],
|
| 266 |
+
"captions": [
|
| 267 |
+
"The sky lights up as the first fireworks burst, signaling the start of a spectacular display.",
|
| 268 |
+
"Intricate fireworks patterns unfold in the sky, each explosion more complex than the last.",
|
| 269 |
+
"The fireworks intensify, filling the sky with a brilliant array of lights and colors that seem to dance in the night.",
|
| 270 |
+
"Two giant fireworks explode at once, their glowing trails creating a breathtaking spectacle for the crowd below.",
|
| 271 |
+
"The deep night sky provides the perfect backdrop for the fireworks, their vibrant colors creating a stunning contrast."
|
| 272 |
+
]
|
| 273 |
+
},
|
| 274 |
+
"16": {
|
| 275 |
+
"title": "LSU: July 2007",
|
| 276 |
+
"steps": [
|
| 277 |
+
"I always enjoy paying a visit to Spitz Laboratories.",
|
| 278 |
+
"Seeing the control panel on some of the old equipment can be fascinating.",
|
| 279 |
+
"Look at this old knob!",
|
| 280 |
+
"Some more lab equipment",
|
| 281 |
+
"We'll celebrate in the hope of one day finding more out there, and to enjoy what we have now."
|
| 282 |
+
],
|
| 283 |
+
"captions": [
|
| 284 |
+
"The dark surface is engraved with the name of Spitz Laboratories, a symbol of innovation and progress.",
|
| 285 |
+
"An antique electronic device rests open, its control panel full of complex dials and switches, hinting at its once-advanced technology.",
|
| 286 |
+
"A hand turns the dial of a vintage machine, setting it to the highest setting, reminiscent of the experimental days gone by.",
|
| 287 |
+
"A collection of historic lab equipment stands in neat rows, a testament to the advancements made over the years.",
|
| 288 |
+
"As a fitting tribute, fireworks explode in the sky, celebrating the spirit of discovery and achievement."
|
| 289 |
+
]
|
| 290 |
+
},
|
| 291 |
+
"17": {
|
| 292 |
+
"title": "Sleepin' and Eatin'",
|
| 293 |
+
"steps": [
|
| 294 |
+
"The dog is being held up, and loved.",
|
| 295 |
+
"The dog will put anything in his mouth",
|
| 296 |
+
"Oh look how cute she is napping. ",
|
| 297 |
+
"The dog is playing with a clear bottle.",
|
| 298 |
+
"The dog is very tired from all the playing."
|
| 299 |
+
],
|
| 300 |
+
"captions": [
|
| 301 |
+
"The puppy gazes up with wide, soulful eyes, being lovingly held in someone's arms.",
|
| 302 |
+
"The dog lies comfortably beside a container, its paw resting gently on top, as if claiming it.",
|
| 303 |
+
"The dog sleeps contentedly on a cozy blanket, its eyes closed in peaceful slumber.",
|
| 304 |
+
"The playful puppy rolls a clear plastic bottle around, its tiny paws having a blast.",
|
| 305 |
+
"Exhausted from play, the dog curls up on the floor and drifts off into a deep sleep."
|
| 306 |
+
]
|
| 307 |
+
},
|
| 308 |
+
"18": {
|
| 309 |
+
"title": "Ribfest - Naperville, IL 4th of July, 2007",
|
| 310 |
+
"steps": [
|
| 311 |
+
"The man and his kid were on the ride.",
|
| 312 |
+
"He was excited.",
|
| 313 |
+
"The kid was not.",
|
| 314 |
+
"What a wild ride this is. So much excitement",
|
| 315 |
+
"The man was having a great time."
|
| 316 |
+
],
|
| 317 |
+
"captions": [
|
| 318 |
+
"The man scrunches up his face in exaggerated fun as the ride begins to lift.",
|
| 319 |
+
"The two men prepare for the thrilling ride ahead, full of excitement and anticipation.",
|
| 320 |
+
"With their hands gripping the restraints, the man and boy brace themselves for the roller coaster.",
|
| 321 |
+
"The two riders sit side by side, preparing for the wild twists and turns of the ride.",
|
| 322 |
+
"The man is thrilled as he enjoys the roller coaster, laughing and screaming with joy."
|
| 323 |
+
]
|
| 324 |
+
},
|
| 325 |
+
"19": {
|
| 326 |
+
"title": "4th of July",
|
| 327 |
+
"steps": [
|
| 328 |
+
"The grill is getting hot.",
|
| 329 |
+
"They had beer to go with it.",
|
| 330 |
+
"and various meat to keep them coming to his house",
|
| 331 |
+
"He cooked them way too long but we ate them anyways. ",
|
| 332 |
+
"The party went into the night."
|
| 333 |
+
],
|
| 334 |
+
"captions": [
|
| 335 |
+
"The grill crackles as flames lick the edges of the barbecue, heating up the meat.",
|
| 336 |
+
"The man sips his beer contentedly, chatting with friends around the grill.",
|
| 337 |
+
"The meat on the plate is still raw, ready to be thrown onto the sizzling barbecue.",
|
| 338 |
+
"Hot dogs and hamburgers sizzle on the grill, the smell filling the air as they cook.",
|
| 339 |
+
"The group of friends laughs and enjoys drinks as the party continues into the night."
|
| 340 |
+
]
|
| 341 |
+
},
|
| 342 |
+
"20": {
|
| 343 |
+
"title": "4th of July",
|
| 344 |
+
"steps": [
|
| 345 |
+
"We waited for sundown so that we could watch the fireworks show.",
|
| 346 |
+
"Finally, the show started!",
|
| 347 |
+
"Bright lights filled the sky!",
|
| 348 |
+
"The finale was spectacular and left us in awe.",
|
| 349 |
+
"There was a lot of smoke in the sky afterwards."
|
| 350 |
+
],
|
| 351 |
+
"captions": [
|
| 352 |
+
"The cross rises against the sky, standing tall as the sun begins to set.",
|
| 353 |
+
"A burst of colorful fireworks lights up the sky, marking the beginning of the show.",
|
| 354 |
+
"Brilliant white fireworks shine in the dark, illuminating the night with their glow.",
|
| 355 |
+
"The grand finale arrives, with two giant fireworks exploding in perfect harmony.",
|
| 356 |
+
"The smoke lingers in the sky, a remnant of the dazzling fireworks that just filled the air."
|
| 357 |
+
]
|
| 358 |
+
},
|
| 359 |
+
"21": {
|
| 360 |
+
"title": "4th of July, 2007 in Sausalito, CA",
|
| 361 |
+
"steps": [
|
| 362 |
+
"The baby was having a great time. He even had a cute hat.",
|
| 363 |
+
"People were starting to arrive in town already.",
|
| 364 |
+
"Mommy then held him up so he could see.",
|
| 365 |
+
"A yellow bug makes it's way past",
|
| 366 |
+
"People rode on horses and were dressed in all sorts of things."
|
| 367 |
+
],
|
| 368 |
+
"captions": [
|
| 369 |
+
"The baby beams with joy, sitting in a stroller, wearing a tiny, adorable hat.",
|
| 370 |
+
"The busy street is filled with pedestrians, as people begin arriving in town for the event.",
|
| 371 |
+
"The woman lifts her son into the air, letting him see all the excitement unfolding around them.",
|
| 372 |
+
"The bright yellow buggy, adorned with flags, moves through the crowd, capturing everyone\u2019s attention.",
|
| 373 |
+
"A rider in elaborate, elegant attire steers their horse through the parade, creating a striking impression."
|
| 374 |
+
]
|
| 375 |
+
},
|
| 376 |
+
"22": {
|
| 377 |
+
"title": "Born on the 4th of July",
|
| 378 |
+
"steps": [
|
| 379 |
+
"It was the 4th of July, and a party was soon to begin.",
|
| 380 |
+
"man about to eat the food ",
|
| 381 |
+
"Sarah and Steve stopped by and ate little burgers too. ",
|
| 382 |
+
"I brought my crazy weird girlfriend home for the first time and sure enough, weirdness ensued. ",
|
| 383 |
+
"Later on a band played. Where they came from I have no idea but it was fun!"
|
| 384 |
+
],
|
| 385 |
+
"captions": [
|
| 386 |
+
"A festive banner hangs in the air, signaling the start of a joyous 4th birthday celebration.",
|
| 387 |
+
"The man prepares to take a large, satisfying bite of his sandwich, eager for the delicious treat.",
|
| 388 |
+
"Sarah and Steve walk hand in hand, enjoying the sights and sounds of the lively street.",
|
| 389 |
+
"The couple playfully poses for the camera, their goofy antics standing out among the crowd.",
|
| 390 |
+
"A talented musician captivates the crowd with their performance, adding a special touch to the event."
|
| 391 |
+
]
|
| 392 |
+
},
|
| 393 |
+
"23": {
|
| 394 |
+
"title": "7/4/7 Fireworks San Diego Bay",
|
| 395 |
+
"steps": [
|
| 396 |
+
"The first firework was let off.",
|
| 397 |
+
"With a boom, two red fireworks burst in the night sky.",
|
| 398 |
+
"The fireworks were beautiful.",
|
| 399 |
+
"Another red burst of fireworks in the sky.",
|
| 400 |
+
"The last was a bit of everything and it all lit the sky. "
|
| 401 |
+
],
|
| 402 |
+
"captions": [
|
| 403 |
+
"The first firework crackles and bursts above the town, lighting up the night.",
|
| 404 |
+
"Two brilliant red fireworks explode simultaneously, their bright trails illuminating the sky.",
|
| 405 |
+
"The dark night sky is filled with dazzling bursts of light from the fireworks above.",
|
| 406 |
+
"The sky comes alive with red and yellow bursts of light, a brilliant display of fireworks.",
|
| 407 |
+
"The final explosion of fireworks fills the air with a grand, awe-inspiring display."
|
| 408 |
+
]
|
| 409 |
+
},
|
| 410 |
+
"24": {
|
| 411 |
+
"title": "4th of July Fireworks - 2007",
|
| 412 |
+
"steps": [
|
| 413 |
+
"The fireworks were bright and beautiful, ",
|
| 414 |
+
"then it became a little more intense with bigger fireworks",
|
| 415 |
+
"they exploded in the sky, ",
|
| 416 |
+
"and then the fireworks were going everywhere when they turned the show up to a 6",
|
| 417 |
+
"then things got even crazier as the show ended"
|
| 418 |
+
],
|
| 419 |
+
"captions": [
|
| 420 |
+
"A series of red fireworks explode, their brilliant light filling the night sky.",
|
| 421 |
+
"The fireworks intensify, with larger explosions lighting up the night in a blur of color.",
|
| 422 |
+
"A single firework bursts in the sky, its vibrant colors bright against the dark background.",
|
| 423 |
+
"The fireworks continue to escalate, lighting up the night with a dazzling display.",
|
| 424 |
+
"The grand finale is a cascade of bright fireworks, filling the sky with their brilliance."
|
| 425 |
+
]
|
| 426 |
+
},
|
| 427 |
+
"25": {
|
| 428 |
+
"title": "Red, White and Boom [Jul '08]",
|
| 429 |
+
"steps": [
|
| 430 |
+
"There was a crowd of people waiting already. ",
|
| 431 |
+
"The clock tower was very tall.",
|
| 432 |
+
"Finally it got dark out, and everyone looked to the skies in anticipation.",
|
| 433 |
+
"the fireworks has stared and it was well worth the time. ",
|
| 434 |
+
"the show is over and now everyone is on there way home. "
|
| 435 |
+
],
|
| 436 |
+
"captions": [
|
| 437 |
+
"A crowd gathers, chatting excitedly as they wait for the event to start.",
|
| 438 |
+
"The clock tower looms tall in front of surrounding buildings, a towering landmark.",
|
| 439 |
+
"As night descends, people look up in awe at the darkening sky, waiting for the fireworks.",
|
| 440 |
+
"Explosions of color light up the sky as the fireworks burst in a dazzling display.",
|
| 441 |
+
"With the show over, people begin to head home, reflecting on the magical evening."
|
| 442 |
+
]
|
| 443 |
+
},
|
| 444 |
+
"26": {
|
| 445 |
+
"title": "Greenville, SC 7/4/08",
|
| 446 |
+
"steps": [
|
| 447 |
+
"The fireworks didn't look very good on the TV.",
|
| 448 |
+
"John had an Idea. He would go see the in person.",
|
| 449 |
+
"Then my dog started barking because he heard the noises too. ",
|
| 450 |
+
"Watching them alone instead",
|
| 451 |
+
"After they were finished we came back in and finished watching our tv show. "
|
| 452 |
+
],
|
| 453 |
+
"captions": [
|
| 454 |
+
"The fireworks appear distant and blurry on the TV screen, failing to capture their true beauty.",
|
| 455 |
+
"Inspired, the young boy decides to head out and see the fireworks live.",
|
| 456 |
+
"As the fireworks explode outside, the dog barks loudly, reacting to the noise.",
|
| 457 |
+
"The night sky glows with vibrant colors as fireworks light up the horizon in a stunning display.",
|
| 458 |
+
"Once the fireworks show concludes, they return to the living room to finish their TV show."
|
| 459 |
+
]
|
| 460 |
+
},
|
| 461 |
+
"27": {
|
| 462 |
+
"title": "Williamsburg, July 2008",
|
| 463 |
+
"steps": [
|
| 464 |
+
"The garden was full of herbs and beautiful plants.",
|
| 465 |
+
"and the gift was a flower, this thing has been growing for years ",
|
| 466 |
+
"The pumpkin was starting to grow larger with each passing week. It was going to be perfect in the Fall.",
|
| 467 |
+
"there was even soliders from the other side there",
|
| 468 |
+
"It was all beautiful and full of life."
|
| 469 |
+
],
|
| 470 |
+
"captions": [
|
| 471 |
+
"The market is filled with an assortment of beautiful plants and fragrant herbs, creating a vibrant atmosphere.",
|
| 472 |
+
"A delicate flower blooms on its stem, adding a touch of elegance to the garden.",
|
| 473 |
+
"The pumpkin grows larger by the day, soon to be ready for harvest in time for Fall.",
|
| 474 |
+
"Soldiers in red coats stand proudly in a field, preparing for their performance with their instruments.",
|
| 475 |
+
"A woman in a gorgeous colonial costume stands in front of the old yellow house, radiating grace and history."
|
| 476 |
+
]
|
| 477 |
+
},
|
| 478 |
+
"28": {
|
| 479 |
+
"title": "4th of July Family BBQ",
|
| 480 |
+
"steps": [
|
| 481 |
+
"I was invited to an outdoor lunch party with lots of people and food. ",
|
| 482 |
+
"The children had fun playing with each other.",
|
| 483 |
+
"Even the dogs were excited. ",
|
| 484 |
+
"Everyone was hanging around and having a great time.",
|
| 485 |
+
"We remember to pose for plenty of pictures."
|
| 486 |
+
],
|
| 487 |
+
"captions": [
|
| 488 |
+
"A lively picnic scene unfolds as many people gather, enjoying food and conversation in the open air.",
|
| 489 |
+
"The young boy and the younger child play together, their laughter filling the air with joy.",
|
| 490 |
+
"Small dogs roam excitedly around the group of people sitting on the patio, adding to the lively atmosphere.",
|
| 491 |
+
"A small group of friends gathers inside, smiling and enjoying each other's company as they chat and laugh.",
|
| 492 |
+
"Before leaving, everyone poses for a group photo, capturing the memories of the fun day together."
|
| 493 |
+
]
|
| 494 |
+
},
|
| 495 |
+
"29": {
|
| 496 |
+
"title": "Fourth of July 08",
|
| 497 |
+
"steps": [
|
| 498 |
+
"The women attend to their children.",
|
| 499 |
+
"But they have other ideas",
|
| 500 |
+
"Let's try this again, maybe if we reposition the kids.",
|
| 501 |
+
"Two out of three is pretty good, but the little guy is still not having it",
|
| 502 |
+
"We ended up only taking one picture. Oh well, pictures aren't for everyone. "
|
| 503 |
+
],
|
| 504 |
+
"captions": [
|
| 505 |
+
"The women look after their children as they spend time together outdoors, enjoying the warm weather.",
|
| 506 |
+
"The children run and play on the grass, laughing and having fun despite their different ideas.",
|
| 507 |
+
"The woman attempts to arrange the children for a photo, trying to get everyone in position.",
|
| 508 |
+
"The children sit together, some more cooperative than others, in a serene moment on the grass.",
|
| 509 |
+
"After much effort, only one picture is taken as the children decide they\u2019ve had enough of the photo session."
|
| 510 |
+
]
|
| 511 |
+
}
|
| 512 |
+
}
|
datasets/recipes.json
ADDED
|
@@ -0,0 +1,471 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"0": {
|
| 3 |
+
"steps": [
|
| 4 |
+
"Heat the Coconut Oil in a wide pan over a medium flame, then add the Onion, Garlic, Scallion, and Ground Black Pepper. Reduce the heat to low for about 3-4 minutes.",
|
| 5 |
+
"Add the Small Shrimp, stir well and cook for another 3 minutes.",
|
| 6 |
+
"Turn the heat up to medium high and add the Jamaican Callaloo, Tomato, Scotch Bonnet Pepper, Fresh Thyme, and Sea Salt. After a couple minutes, add the Water and cook until tender.",
|
| 7 |
+
"After about 10-12 minutes, taste for salt and adjust accordingly."
|
| 8 |
+
],
|
| 9 |
+
"title": "Jamaican Callaloo With Shrimp",
|
| 10 |
+
"captions": [
|
| 11 |
+
"Pan with sizzling coconut oil, onions, garlic, scallions, and black pepper",
|
| 12 |
+
"Pan with saut\u00e9ed aromatics and added shrimp",
|
| 13 |
+
"Pan with saut\u00e9ed aromatics, shrimp, Jamaican callaloo, tomato, scotch bonnet pepper, thyme, and sea salt",
|
| 14 |
+
"Pan with simmering Jamaican callaloo shrimp dish"
|
| 15 |
+
]
|
| 16 |
+
},
|
| 17 |
+
"2": {
|
| 18 |
+
"steps": [
|
| 19 |
+
"To a medium bowl, add Pecans, Vegan Cream Cheese, Daiya\u00ae Mozzarella Cheese, Sun-Dried Tomatoes in Olive Oil, Garlic, Ground Black Pepper, and Vegan Basil Pesto. Stir until well combined.",
|
| 20 |
+
"Add Fresh Spinach to the mixture and continue stirring until all ingredients are well mixed.",
|
| 21 |
+
"Lay out Tortilla, divide cheese/pesto/tomato mixture evenly among the four tortillas, spreading in a thin layer until it coats the whole tortilla up to the outer edge. Tear and sprinkle approximately 5 Fresh Basil Leaf over each tortilla.",
|
| 22 |
+
"Gently roll tortillas, keeping them fairly tight, then slice each into 8 pieces. Serve immediately or store in the refrigerator for up to 3 days."
|
| 23 |
+
],
|
| 24 |
+
"title": "Vegan Basil Pesto and Sun-Dried Tomato Pinwheels",
|
| 25 |
+
"captions": [
|
| 26 |
+
"Bowl with pecans, vegan cream cheese, Daiya mozzarella, sun-dried tomatoes, garlic, black pepper, and vegan basil pesto",
|
| 27 |
+
"Bowl with filling ingredients and added spinach",
|
| 28 |
+
"Tortilla with spread filling and basil leaves",
|
| 29 |
+
"Rolled and sliced vegan quesadilla"
|
| 30 |
+
]
|
| 31 |
+
},
|
| 32 |
+
"3": {
|
| 33 |
+
"steps": [
|
| 34 |
+
"Melt butter in a small pot over medium heat.",
|
| 35 |
+
"Add egg and sugar to a bowl and whisk until combined. Stir in honey and add lemon zest. Stir to combine until a smooth batter forms.",
|
| 36 |
+
"Sieve flour and baking powder into the batter, then add melted butter and stir to combine. Cover bowl with plastic wrap and let rest in the fridge for at least 3 hrs.",
|
| 37 |
+
"Pre-heat oven to 210\u00b0C/410\u00b0F. Grease baking pan with butter. Remove batter from the fridge and transfer into a piping bag. Cut off the tip and pipe batter into baking pan up to three quarters, so the madeleines have enough space to rise.",
|
| 38 |
+
"Reduce baking temperature to 170\u00b0C/350\u00b0F and bake madeleines for approx. 12 \u2013 15 min. until golden brown. Dust with confectioner\u2019s sugar and"
|
| 39 |
+
],
|
| 40 |
+
"title": "Madeleines",
|
| 41 |
+
"captions": [
|
| 42 |
+
"Small pot with melting butter",
|
| 43 |
+
"Bowl with whisked eggs, sugar, honey, and lemon zest",
|
| 44 |
+
"Bowl with combined batter",
|
| 45 |
+
"Covered bowl of batter in the fridge",
|
| 46 |
+
"Baking pan with piped madeleine batter"
|
| 47 |
+
]
|
| 48 |
+
},
|
| 49 |
+
"4": {
|
| 50 |
+
"steps": [
|
| 51 |
+
"Preheat oven to 180\u00b0C/350\u00b0F and grease springform pan with coconut oil. For the crust, pulse oats in a food processor to a fine flour. Add buckwheat flour, coconut oil, maple syrup, some cinnamon, baking powder, and a pinch of salt, and pulse to form a crust. If the mixture is too dry, carefully add water a tbsp. at a time to make the crust moldable.",
|
| 52 |
+
"Use hands to press two-thirds of the dough evenly into springform pan along the base and border. Lightly flour work surface and remaining dough. Roll out, using a rolling pin. Use a cookie cutter to cut out decorative shapes, or roll out dough into a round the size of the pan, if you prefer.",
|
| 53 |
+
"For the filling, peel and quarter apples. Remove core and slice.",
|
| 54 |
+
"In a large bowl, thoroughly mix apple slices, some cinnamon, nutmeg, lemon juice, agave syrup, arrowroot flour, coconut sugar, speculaas spice, and salt.",
|
| 55 |
+
"Transfer filling to prepared springform pan and spread evenly.",
|
| 56 |
+
"Cover filling with either with cookie cut-outs or a round of dough. For the latter, pierce top with a fork to allow steam to escape while baking. Place in preheated oven and bake at 180\u00b0C/350\u00b0F for approx. 30 min. Cover with aluminum foil and press down lightly so that the apple juice rises to the top and soaks the entire cake. Bake for approx. 45 \u2013 60 min. more, until golden brown. Allow to cool completely on a cooling rack before cutting."
|
| 57 |
+
],
|
| 58 |
+
"title": "Gluten-free apple cake",
|
| 59 |
+
"captions": [
|
| 60 |
+
"Close-up view of a food processor blending ingredients for a cake crust.",
|
| 61 |
+
"A rolling pin rolling out dough on a wooden surface.",
|
| 62 |
+
"Sliced apples on a wooden cutting board.",
|
| 63 |
+
"A large bowl filled with apple slices, cinnamon, nutmeg, lemon juice, agave syrup, arrowroot flour, coconut sugar, speculaas spice, and salt, being stirred.",
|
| 64 |
+
"A layer of apple filling being spread evenly inside a springform pan.",
|
| 65 |
+
"A hand using a fork to prick the top of an apple cake in a springform pan before baking."
|
| 66 |
+
]
|
| 67 |
+
},
|
| 68 |
+
"7": {
|
| 69 |
+
"steps": [
|
| 70 |
+
"Preheat oven to 200\u00b0C/400\u00b0F. Pierce skin of sweet potatoes approx. 5 to 7 times with a fork. Then, place on a parchment-lined baking sheet, transfer to oven, and bake at 200\u00b0C/400\u00b0F for approx. 45 \u2013 60 min. Once baking time is finished, turn off oven and leave potatoes in oven until the other steps are complete.",
|
| 71 |
+
"Mince garlic. Cut lemon into wedges and halve pomegranate. Remove seeds from pomegranate.",
|
| 72 |
+
"In a large, grease-free frying pan, toast pine nuts over medium heat for approx. 1 \u20132 min. until fragrant and golden brown. Remove from pan and set aside.",
|
| 73 |
+
"Add some of the coconut oil to pan, saut\u00e9 garlic, and wilt spinach over medium heat for approx. 1 \u2013 2 min. Drizzle with part of the lemon juice. Add toasted pine nuts to spinach and set aside.",
|
| 74 |
+
"Remove potatoes from oven and cut in half. Add rest of coconut oil to potato halves and mash with fork.",
|
| 75 |
+
"Spoon spinach and pine nut mixture on top of potatoes. Add some more lemon juice. Drizzle with yogurt on top and garnish with pomegranate seeds. Season with salt and pepper to taste."
|
| 76 |
+
],
|
| 77 |
+
"title": "Baked sweet potatoes with spinach and pine nuts",
|
| 78 |
+
"captions": [
|
| 79 |
+
"A baking sheet lined with parchment paper holding several sweet potatoes, pierced with forks.",
|
| 80 |
+
"A close-up shot of minced garlic, lemon wedges, and a halved pomegranate with its seeds visible.",
|
| 81 |
+
"A frying pan with toasted pine nuts, golden brown in color.",
|
| 82 |
+
"A frying pan with saut\u00e9ed garlic and wilted spinach, along with toasted pine nuts.",
|
| 83 |
+
"Baked sweet potatoes cut in half, with coconut oil added and being mashed with a fork.",
|
| 84 |
+
"Baked sweet potatoes topped with a spinach and pine nut mixture, a drizzle of lemon juice and yogurt, pomegranate seeds, and a sprinkle of salt and pepper."
|
| 85 |
+
]
|
| 86 |
+
},
|
| 87 |
+
"8": {
|
| 88 |
+
"steps": [
|
| 89 |
+
"Place eggs and egg white, flour, evaporated milk, sugar, lemon peel, vanilla extract and salt in blender; cover. Blend until smooth. Scrape down sides and blend again if needed. Let mixture sit for approx. 10 min.",
|
| 90 |
+
"Meanwhile, place an ovenproof frying pan in oven and preheat to 220\u00b0C/425\u00b0F. Remove frying pan from oven.",
|
| 91 |
+
"Add butter to frying pan and swirl to coat all sides. Add batter to pan.",
|
| 92 |
+
"Bake for 15 \u2013 20 min. at 220\u00b0C/425\u00b0F, or until puffed and golden. Edges should be deep golden brown and crisp.",
|
| 93 |
+
"Slide Dutch baby onto serving platter or cutting board, or serve straight from pan, if desired. Top with fresh berries and sprinkle with lemon juice. Dust with confectioner's sugar and cut into wedges for serving. Serve warm with maple syrup."
|
| 94 |
+
],
|
| 95 |
+
"title": "Dutch baby",
|
| 96 |
+
"captions": [
|
| 97 |
+
"Close-up view of a blender filled with a creamy mixture of eggs, flour, evaporated milk, sugar, lemon peel, vanilla extract, and salt.",
|
| 98 |
+
"An ovenproof frying pan is carefully placed into a preheating oven set to 220\u00b0C/425\u00b0F.",
|
| 99 |
+
"A person is pouring a smooth batter into a buttered frying pan.",
|
| 100 |
+
"A golden-brown Dutch baby pancake is baking in a hot oven at 220\u00b0C/425\u00b0F.",
|
| 101 |
+
"A woman uses a knife to cut a delicious-looking Dutch baby pancake into even wedges on a wooden cutting board.\n"
|
| 102 |
+
]
|
| 103 |
+
},
|
| 104 |
+
"9": {
|
| 105 |
+
"steps": [
|
| 106 |
+
"Preheat the oven to 120\u00b0C/250\u00b0F. Heat (don't boil!) heavy cream with some of the sugar and vanilla seeds until the sugar has dissolved.",
|
| 107 |
+
"Next, whisk the warm mixture into the egg yolks in a large bowl.",
|
| 108 |
+
"Pour the mixture into br\u00fbl\u00e9e tins and place these into a tall baking dish. Pour hot water into the baking dish, creating a water bath in which to cook the cr\u00e8me br\u00fbl\u00e9e.",
|
| 109 |
+
"Bake in a preheated oven at 120\u00b0C/250\u00b0F for approx. 60 min. Next, remove the tins from the water bath and leave to cool for 30 min. Chill for at least four hours or overnight before serving.",
|
| 110 |
+
"Caramelize rest of the sugar in a small frying pan. Add a pinch of salt, pour in water and reduce into a sauce. Pour over the Crema Catalana to serve."
|
| 111 |
+
],
|
| 112 |
+
"title": "Crema Catalana with salted caramel sauce",
|
| 113 |
+
"captions": [
|
| 114 |
+
"Close-up view of a pot of heavy cream simmering gently on a stovetop burner.",
|
| 115 |
+
"A woman vigorously whisking a creamy mixture into egg yolks in a large mixing bowl.",
|
| 116 |
+
"A woman carefully pouring a custard mixture into individual ramekins, then arranging them in a larger baking dish. Hot water is being added to the baking dish, creating a water bath around the ramekins.",
|
| 117 |
+
"A woman removing a baking dish containing ramekins from a preheated oven. The ramekins are slightly browned on top.",
|
| 118 |
+
"A woman sprinkling granulated sugar into a small, hot frying pan.\n"
|
| 119 |
+
]
|
| 120 |
+
},
|
| 121 |
+
"10": {
|
| 122 |
+
"steps": [
|
| 123 |
+
"Preheat oven to 180\u00b0C/350\u00b0F. Grease and flour the cake pan. Line the bottom with parchment paper if it does not have a removable bottom. Zest all lemons and juice half of them. Set zest aside. In a medium bowl, combine flour, baking powder, and salt. In a measuring cup, mix together milk and lemon juice.",
|
| 124 |
+
"Beat together butter, sugar, lemon zest, and some of the vanilla sugar until smooth. Add eggs one at a time, beating after each incorporation. Add half of the flour, mix to incorporate, then add the milk mixture and remaining flour. Stir until fully combined.",
|
| 125 |
+
"Transfer batter to cake pan, smooth evenly, then bake at 180\u00b0C/350\u00b0F for approx. 20 \u2013 30 min. Cool for approx. 10 min., then transfer to a wire rack to cool completely.",
|
| 126 |
+
"Meanwhile, make frosting: Add cr\u00e8me fra\u00eeche, powdered sugar, and remaining vanilla sugar to a medium mixing bowl. Beat until combined and thickened slightly. Add a drop or two of food coloring until the desired shade of pink is reached. Stir until evenly incorporated.",
|
| 127 |
+
"Smooth frosting over cake, decorate with sprinkles if desired, and"
|
| 128 |
+
],
|
| 129 |
+
"title": "Tangy lemon sheet cake",
|
| 130 |
+
"captions": [
|
| 131 |
+
"Close-up view of a woman pouring milk into a measuring cup next to a small bowl of lemon juice.",
|
| 132 |
+
"A woman beating a mixture of butter, sugar, lemon zest, and vanilla sugar in a mixing bowl. Eggs are added one at a time. Flour and milk mixture are gradually incorporated.",
|
| 133 |
+
"A woman carefully pouring batter into a cake pan and smoothing the top with a spatula.",
|
| 134 |
+
"A woman mixing cr\u00e8me fra\u00eeche, powdered sugar, and vanilla sugar in a bowl.",
|
| 135 |
+
"A woman decorating a frosted cake with sprinkles and frosting.\n"
|
| 136 |
+
]
|
| 137 |
+
},
|
| 138 |
+
"13": {
|
| 139 |
+
"steps": [
|
| 140 |
+
"Finely chop rosemary. Combine buttermilk, lime zest, chopped rosemary, paprika, salt, and pepper. Add pressed garlic and stir to combine.",
|
| 141 |
+
"Pour buttermilk mixture into a freezer bag. Add chicken wings and mix well. Transfer to refrigerator and let marinate for approx. 2 hours.",
|
| 142 |
+
"Add bread crumbs to a large bowl. Coat chicken wings with bread crumbs, using tongs to make sure they are coated on all sides.",
|
| 143 |
+
"Heat a generous amount of vegetable oil in a frying pan. Once oil is hot, add chicken wings and cook until browned and cooked through, approx. 8 \u2013 10 min. Rotate to cook on all sides. Enjoy with your favorite dipping sauce."
|
| 144 |
+
],
|
| 145 |
+
"title": "Buttermilk chicken wings",
|
| 146 |
+
"captions": [
|
| 147 |
+
"A bowl containing finely chopped rosemary, buttermilk, lime zest, paprika, salt, pepper, and pressed garlic.",
|
| 148 |
+
"A freezer bag filled with chicken wings submerged in a buttermilk mixture.",
|
| 149 |
+
"Chicken wings coated in breadcrumbs in a large bowl.",
|
| 150 |
+
"A frying pan with chicken wings being fried in hot vegetable oil."
|
| 151 |
+
]
|
| 152 |
+
},
|
| 153 |
+
"14": {
|
| 154 |
+
"steps": [
|
| 155 |
+
"Cut the Vanilla Bean Pod in half, then halve them lengthwise as well.",
|
| 156 |
+
"Prepare a 100-milliliter jar that has a sealable lid, and put the vanilla in it. Fill up the jar to the brim with Vodka.",
|
| 157 |
+
"Seal the jar, and store the mix in a cool, dark place for about three months. This will give time to the vanilla to infuse the vodka with its taste. The longer you leave it, the more infused the flavors will be."
|
| 158 |
+
],
|
| 159 |
+
"title": "Home Made Vanilla Extract",
|
| 160 |
+
"captions": [
|
| 161 |
+
"A vanilla bean pod being halved with a sharp knife.",
|
| 162 |
+
"A jar with a sealable lid, filled partially with a substance and a wooden spoon resting inside.",
|
| 163 |
+
"A sealed jar rests on a wooden table next to a bottle of vodka.\n"
|
| 164 |
+
]
|
| 165 |
+
},
|
| 166 |
+
"15": {
|
| 167 |
+
"steps": [
|
| 168 |
+
"In a bowl, add Milk, Granulated Sugar, Cream, and Vanilla Extract. Whisk until combined.",
|
| 169 |
+
"Pour into ice cream churner. Churn for 12-15 minutes.",
|
| 170 |
+
"Refrigerate for 30 minutes.",
|
| 171 |
+
"Add M&M's\u00ae Milk Chocolate Minis. Mix through."
|
| 172 |
+
],
|
| 173 |
+
"title": "Homemade McDonald's McFlurry",
|
| 174 |
+
"captions": [
|
| 175 |
+
"A bowl containing milk, granulated sugar, cream, and vanilla extract.",
|
| 176 |
+
"Milk being poured into a blender.",
|
| 177 |
+
"A bowl of ice cream being placed in a refrigerator.",
|
| 178 |
+
"A bowl of chocolate M&Ms on a white table.\n"
|
| 179 |
+
]
|
| 180 |
+
},
|
| 181 |
+
"18": {
|
| 182 |
+
"steps": [
|
| 183 |
+
"Using a mandolin with the julienne attachment, slice the Zucchini on all four sides into spaghetti-like strands. Stop before you reach the seeds.",
|
| 184 |
+
"Tear the Fresh Mint Leaves or thinly slice with a knife by dragging it across to prevent bruising.",
|
| 185 |
+
"Toss the zucchini in a bowl with the Extra-Virgin Olive Oil, Lemon, and torn mint leaves. Season with Kosher Salt and freshly ground Ground Black Pepper.",
|
| 186 |
+
"Using a vegetable peeler, make shavings of the Pecorino Romano Cheese. You can also finely grate the cheese with a microplane."
|
| 187 |
+
],
|
| 188 |
+
"title": "Zucchini, Pecorino & Mint Salad",
|
| 189 |
+
"captions": [
|
| 190 |
+
"Close-up view of a woman using a mandolin slicer with the julienne blade to create thin zucchini noodles.",
|
| 191 |
+
"A hand using a knife to finely chop fresh mint leaves on a wooden cutting board.",
|
| 192 |
+
"A glass bowl filled with zucchini noodles being tossed with olive oil, lemon juice, torn mint leaves, salt, and pepper.",
|
| 193 |
+
"A hand using a vegetable peeler to create thin shavings of Pecorino Romano cheese.\n"
|
| 194 |
+
]
|
| 195 |
+
},
|
| 196 |
+
"22": {
|
| 197 |
+
"steps": [
|
| 198 |
+
"Chop pistachios. Peel and fillet oranges, mandarins, and grapefruit, reserving the juice. Set aside in a bowl",
|
| 199 |
+
"Mix yogurt, cinnamon, and vanilla sugar in a bowl and set aside. In another mixing bowl, whisk together eggs and milk. Cut panettone into 2-cm/0.66-in. thick slices and soak each side in egg mixture.",
|
| 200 |
+
"In a frying pan, melt butter over medium heat, and fry panettone for approx. 3 min. on each side, or until golden brown.",
|
| 201 |
+
"Serve French toast warm with yogurt and citrus fruits. Sprinkle with pistachios."
|
| 202 |
+
],
|
| 203 |
+
"title": "Panettone French toast",
|
| 204 |
+
"captions": [
|
| 205 |
+
"Close-up view of a woman's hands skillfully chopping pistachios on a wooden cutting board using a sharp knife.",
|
| 206 |
+
"A woman carefully cuts a slice of panettone, then dips it into a bowl of lightly beaten egg mixture.",
|
| 207 |
+
"Golden-brown slices of panettone are frying in a hot pan on a stovetop.",
|
| 208 |
+
"A plate of delicious-looking panettone French toast, garnished with creamy yogurt and segments of fresh citrus fruit.\n"
|
| 209 |
+
]
|
| 210 |
+
},
|
| 211 |
+
"24": {
|
| 212 |
+
"steps": [
|
| 213 |
+
"Halve pomegranate, deseed, and set aside. Finely chop garlic and set aside. Finely chop mint. Add yogurt to a bowl and mix with chopped mint and cumin. Add salt and sugar to taste.",
|
| 214 |
+
"Preheat oven to 180\u00b0C/350\u00b0F. Heat olive oil in a pan over medium-high heat. Season lamb with salt and pepper and sear for approx. 2 min. on both sides along with chopped garlic. Remove from pan and set aside. In another pan, toast pistachios over medium-high heat for approx. 2 min. Set aside.",
|
| 215 |
+
"Transfer pita bread to oven and toast for approx. 2 min. on 180\u00b0C/350\u00b0F. Thinly slice lamb fillet.",
|
| 216 |
+
"Remove pita bread from oven and fill with yogurt sauce, pomegranate seeds, toasted pistachios, and thinly sliced lamb. Serve immediately."
|
| 217 |
+
],
|
| 218 |
+
"title": "Lamb and pomegranate sandwich",
|
| 219 |
+
"captions": [
|
| 220 |
+
"Close-up view of hands using a knife to chop a pomegranate on a wooden cutting board.",
|
| 221 |
+
"A pan on a stovetop with lamb cooking, showing some browning and sizzling.",
|
| 222 |
+
"A person slicing a lamb fillet on a wooden cutting board with a knife.",
|
| 223 |
+
"A pita bread being filled with yogurt sauce, pomegranate seeds, toasted pistachios, and thinly sliced lamb.\n"
|
| 224 |
+
]
|
| 225 |
+
},
|
| 226 |
+
"26": {
|
| 227 |
+
"steps": [
|
| 228 |
+
"Cut the upper half off the Bread Boule. Carve out the bread from the bottom half to form a bowl.",
|
| 229 |
+
"Add the Campbell's New England Clam Chowder, Milk and Cream into a pan. Season with Ground Black Pepper.",
|
| 230 |
+
"Heat over medium high heat and stir everything together. Heat to a boil, and it is ready to serve.",
|
| 231 |
+
"Ladle soup into the bread bowl. Finely chop some Fresh Parsley and/or Fresh Chives for garnish."
|
| 232 |
+
],
|
| 233 |
+
"title": "New England Clam Chowder",
|
| 234 |
+
"captions": [
|
| 235 |
+
"Close-up of hands carefully carving out the inside of a bread boule, creating a bread bowl.",
|
| 236 |
+
"A cast iron pan containing a bread bowl filled with a dark, seasoned soup.",
|
| 237 |
+
"A cast iron pan containing a bread bowl filled with a dark, seasoned soup.",
|
| 238 |
+
"A rustic wooden table with a bread bowl filled with soup, a spoon resting inside, and a piece of bread on the side.\n"
|
| 239 |
+
]
|
| 240 |
+
},
|
| 241 |
+
"27": {
|
| 242 |
+
"steps": [
|
| 243 |
+
"Cook pasta in plenty of salted boiling water, according to package instructions, for approx. 10 \u2013 12 min. until al dente. Drain, save some pasta water, and set aside.",
|
| 244 |
+
"Peel onion and garlic cloves and chop finely. Dice eggplant into cubes.",
|
| 245 |
+
"Heat up some olive oil in a large frying pan and saut\u00e9 onion and garlic for about 2 \u2013 4 min. until translucent. Add eggplant to pan and fry for approx. 6 \u2013 8 min. until browned on all sides and somewhat soft.",
|
| 246 |
+
"Add whole peeled tomatoes and thyme leaves. Boil everything over medium heat for about 5 \u2013 8 min. Season generously with salt and pepper. Toss cooked pasta in the sauce and serve in deep plates with a dollop of ricotta and fresh basil."
|
| 247 |
+
],
|
| 248 |
+
"title": "Whole wheat pasta alla norma",
|
| 249 |
+
"captions": [
|
| 250 |
+
"Close-up view of a pot of boiling pasta on a stovetop.",
|
| 251 |
+
"A person chopping an onion and eggplant on a wooden cutting board.",
|
| 252 |
+
"A frying pan on a stovetop with eggplant cooking in it.",
|
| 253 |
+
"A frying pan on a stovetop with pasta cooking in it.\n"
|
| 254 |
+
]
|
| 255 |
+
},
|
| 256 |
+
"28": {
|
| 257 |
+
"steps": [
|
| 258 |
+
"Bring a pot of water to a boil on the stove top. Add Elbow Macaroni, and cook until al dente, about 8-10 minutes.",
|
| 259 |
+
"In a separate pan, over medium heat, melt the Butter. Once melted, pour in Milk and plain All-Purpose Flour. Whisk until flour is completely dissolved. Continue stirring until mixture comes to a boil.",
|
| 260 |
+
"Turn heat down to a simmer, stirring constantly, and cook for 2 minutes. Add Cheddar Cheese, and mix until cheese is fully melted.",
|
| 261 |
+
"Add drained macaroni, and mix until thoroughly combined."
|
| 262 |
+
],
|
| 263 |
+
"title": "Macaroni and Cheese",
|
| 264 |
+
"captions": [
|
| 265 |
+
"A pot of boiling water with elbow macaroni cooking on a stovetop.",
|
| 266 |
+
"A saucepan with milk and flour simmering on a stovetop.",
|
| 267 |
+
"A saucepan with cheese sauce, made from cheese and flour, bubbling on a stovetop.",
|
| 268 |
+
"A pan containing macaroni and cheese, ready to be served, on a stovetop.\n"
|
| 269 |
+
]
|
| 270 |
+
},
|
| 271 |
+
"31": {
|
| 272 |
+
"steps": [
|
| 273 |
+
"Add rolled oats, coconut milk, almond milk, vanilla extract, ground cinnamon, and ground cardamom to a pot over medium-high heat and bring to a simmer. Reduce heat to medium-low, cover, and let cook for approx. 10 min., or until the oats are soft and almost all liquid is absorbed.",
|
| 274 |
+
"In the meantime, toast cashews in a frying pan until fragrant. Remove from heat and set aside.",
|
| 275 |
+
"As soon as the porridge is done, remove from heat, add toasted cashews and honey, and stir to combine.",
|
| 276 |
+
"Peel and slice mango. Serve warm porridge in bowls and top with sliced mango. Sprinkle with coconut flakes, cocoa nibs, and black sesame seeds. Drizzle with some more honey, if desired, and"
|
| 277 |
+
],
|
| 278 |
+
"title": "Honey-coconut porridge",
|
| 279 |
+
"captions": [
|
| 280 |
+
"A pot on a stovetop containing oatmeal simmering in coconut milk, almond milk, vanilla extract, ground cinnamon, and ground cardamom.",
|
| 281 |
+
"A frying pan with toasted cashews.",
|
| 282 |
+
"A pot of oatmeal being stirred with a spoon and a wooden spoon.",
|
| 283 |
+
"A bowl of oatmeal topped with sliced mango, coconut flakes, cocoa nibs, and black sesame seeds.\n"
|
| 284 |
+
]
|
| 285 |
+
},
|
| 286 |
+
"32": {
|
| 287 |
+
"steps": [
|
| 288 |
+
"Add Beef Rump Roast, Pepperoncini Pepper, Dry Italian Salad Dressing Mix, Brown Gravy Mix, and Water to the Instant Pot.",
|
| 289 |
+
"Close and lock lid. Cook on Manual High Pressure for 60 minutes, then natural release pressure.",
|
| 290 |
+
"Rest for 5 minutes. Shred big chunks of beef to allow juice and peppers to mix in with the meat.",
|
| 291 |
+
"Serve alone, with side dishes, on a sandwich or any way you want!"
|
| 292 |
+
],
|
| 293 |
+
"title": "Instant Pot Pepperoncini Italian Beef",
|
| 294 |
+
"captions": [
|
| 295 |
+
"A woman adds beef rump roast, pepperoncini peppers, dry Italian salad dressing mix, brown gravy mix, and water to an Instant Pot.",
|
| 296 |
+
"An Instant Pot cooking a beef roast submerged in water.",
|
| 297 |
+
"A woman shreds large chunks of beef, allowing the juices and peppers to mix with the meat.",
|
| 298 |
+
"A bowl of shredded beef soup served on a wooden table.\n"
|
| 299 |
+
]
|
| 300 |
+
},
|
| 301 |
+
"35": {
|
| 302 |
+
"steps": [
|
| 303 |
+
"Add Chicken Backbones, Fennel Bulb, Onion, Bay Leaf, Black Peppercorns, Fresh Ginger, Garlic, and Jalape\u00f1o Pepper to a stock pot. Cover with Water.",
|
| 304 |
+
"Bring to boil. Reduce to a light simmer. Cover. Cook 24-48 hours on lowest setting.",
|
| 305 |
+
"Season withSoy Sauce to taste before serving!"
|
| 306 |
+
],
|
| 307 |
+
"title": "Bone Broth",
|
| 308 |
+
"captions": [
|
| 309 |
+
"A stock pot filled with chicken backbones, fennel bulb, onion, bay leaf, black peppercorns, fresh ginger, garlic, and jalape\u00f1o pepper.",
|
| 310 |
+
"A pot of soup simmering on a stove top.",
|
| 311 |
+
"A bowl of finished soup with a spoon resting in it.\n"
|
| 312 |
+
]
|
| 313 |
+
},
|
| 314 |
+
"39": {
|
| 315 |
+
"steps": [
|
| 316 |
+
"Slice off both ends of the oranges. Then, cut off the remaining peel and remaining pith, if necessary. Fillet them over a small bowl by cutting down along the sides of the inner membrane to get segments. Add juice from the segmented oranges to the bowl.",
|
| 317 |
+
"Caramelize sugar in a frying pan over medium heat and deglaze with orange segments and juice. Let simmer for approx. 2 min.",
|
| 318 |
+
"In a heatproof bowl over a pot of simmering water, melt white chocolate. Add heavy cream to a bowl and whip with a hand mixer with beaters until soft peaks form. In another bowl, mix Greek yogurt with melted white chocolate. Carefully fold the whipped cream into the yogurt- mixture, one half at a time. Transfer to a piping bag and chill for approx. 1 hr.",
|
| 319 |
+
"Layer yogurt-white chocolate cream, oranges, and chopped pistachios in serving glasses. Garnish with white chocolate shavings and"
|
| 320 |
+
],
|
| 321 |
+
"title": "Creamy yogurt-white chocolate parfait with orange",
|
| 322 |
+
"captions": [
|
| 323 |
+
"A woman carefully peeling an orange.",
|
| 324 |
+
"A frying pan with glistening caramelized sugar.",
|
| 325 |
+
"A bowl of melted white chocolate and another bowl of whipped cream; a third bowl contains a mixture of Greek yogurt and melted white chocolate.",
|
| 326 |
+
"Elegant serving glasses filled with layers of yogurt-white chocolate cream, orange segments, and chopped pistachios, garnished with white chocolate shavings.\n"
|
| 327 |
+
]
|
| 328 |
+
},
|
| 329 |
+
"41": {
|
| 330 |
+
"steps": [
|
| 331 |
+
"Measure out semolina and flour onto a clean working surface. Form a hollow in the middle and add eggs. Whisk eggs with a fork and incorporate flour little by little, then knead to combine. If needed, add some water. Knead dough for approx. 10 min., wrap in plastic wrap, and let rest for approx. 30 min.",
|
| 332 |
+
"In the meantime, add potatoes to a large pot and cover with water, then season with salt. Cook for approx. 20 min., or until fork-tender. In the meantime, brown butter in a small pot and let cool down. Slice mint into thin ribbons.",
|
| 333 |
+
"Drain potatoes, add to a bowl, and mash with a fork. Add grated Parmesan cheese, browned butter, salt, pepper, mint, and stir to combine.",
|
| 334 |
+
"Quarter pasta dough and use a pasta machine to roll out the dough. Stamp out discs of dough for the ravioli with a round cookie cutter. Add a spoonful of potato and mint filling to one disc and brush the dough with some water. Place a second disc of dough on top and press around the edges to seal. Repeat the process with remaining dough and filling.",
|
| 335 |
+
"Bring a large pot water to a boil, salt well, and cook ravioli for approx. 5 min. In the meantime, melt butter in a large frying pan and add sage leaves and a ladle of cooking water from the ravioli. Add ravioli to the frying pan and toss to coat. Serve ravioli with fresh mint and black pepper."
|
| 336 |
+
],
|
| 337 |
+
"title": "Potato and mint ravioli with sage butter",
|
| 338 |
+
"captions": [
|
| 339 |
+
"A clean work surface with measured semolina and flour, a well made in the center, eggs added to the well, and a fork whisking the eggs while incorporating the flour.",
|
| 340 |
+
"A large pot of boiling water with potatoes and salt.",
|
| 341 |
+
"A bowl of fluffy mashed potatoes being stirred with a fork.",
|
| 342 |
+
"A pasta machine rolling out dough, round ravioli cutouts brushed with water, a spoonful of potato and mint filling added to one disc, and the edges sealed.",
|
| 343 |
+
"A pot of boiling ravioli, a frying pan with melted butter and sage, and cooked ravioli tossed in the butter and sage, ready to be served.\n"
|
| 344 |
+
]
|
| 345 |
+
},
|
| 346 |
+
"42": {
|
| 347 |
+
"steps": [
|
| 348 |
+
"Pre-heat oven to 210\u00b0C/410\u00b0F. Slice sweet potato approx. 1-in. thick. Peel and cut onion into wedges. Peel and finely dice garlic. Melt coconut oil in a small pot over low heat.",
|
| 349 |
+
"Add sliced sweet potato, onion, shredded coconut, melted coconut oil, garlic, sea salt, and pepper to a baking sheet and toss to coat. Bake at 210\u00b0C/410\u00b0F for approx. 20 min. Then remove from the oven and let cool down a bit.",
|
| 350 |
+
"Peel and chop ginger. Transfer sweet potato mixture to a blender. Add ginger, lemon zest, hot vegetable stock, and orange juice. Blend for approx. 40 sec. on high, or until the mixture is smooth. Season with salt and pepper to taste.",
|
| 351 |
+
"Add coconut flakes to a pan set over medium heat and toast until they are slightly browned. Transfer soup to serving bowls. Serve with diced mango, toasted coconut flakes, sliced green onion, chopped cilantro, and lime zest on top.",
|
| 352 |
+
"This and many more quick recipes can be found in Sebastian Copien\u00b4s cookbook \u201cFit-Mix\u201d (ZS Verlag)."
|
| 353 |
+
],
|
| 354 |
+
"title": "Sweet potato and orange soup",
|
| 355 |
+
"captions": [
|
| 356 |
+
"Close-up view of hands slicing a sweet potato on a wooden cutting board.",
|
| 357 |
+
"A baking sheet filled with sliced sweet potatoes, onions, shredded coconut, and seasonings.",
|
| 358 |
+
"A blender filled with cooked sweet potato, creating a smooth puree.",
|
| 359 |
+
"A pan with toasted coconut flakes, lightly browned and fragrant.\n"
|
| 360 |
+
]
|
| 361 |
+
},
|
| 362 |
+
"43": {
|
| 363 |
+
"steps": [
|
| 364 |
+
"In a large bowl, mix together flour, water, oil, and salt and knead until a smooth dough forms. Cover with kitchen towel and let rest for approx. 15 min.",
|
| 365 |
+
"In a small bowl, season cr\u00e8me fra\u00eeche with nutmeg and pepper. Dice bacon and thinly slice onions. Finely chop chives and set aside.",
|
| 366 |
+
"Preheat oven to 220\u00b0C/425\u00b0F. Roll out dough onto a sheet of parchment paper. Transfer to a baking sheet covered with parchment paper. Spread cr\u00e8me fra\u00eeche over dough and top with onion rings and diced bacon.",
|
| 367 |
+
"Bake at 220\u00b0C/425\u00b0F for approx. 15 \u2013 20 min. Garnish with chopped chives and season with more pepper to taste."
|
| 368 |
+
],
|
| 369 |
+
"title": "Shortcut tarte flamb\u00e9e",
|
| 370 |
+
"captions": [
|
| 371 |
+
"Close-up view of hands kneading dough in a large bowl using a wooden spoon.",
|
| 372 |
+
"A small bowl containing cr\u00e8me fra\u00eeche, with a sprinkle of nutmeg and pepper nearby. Diced bacon, thinly sliced onions, and finely chopped chives are arranged separately on a surface.",
|
| 373 |
+
"A person rolling out a circle of dough on a sheet of parchment paper, then carefully transferring it to a baking sheet lined with parchment paper.",
|
| 374 |
+
"A person gently placing a round cake onto a baking sheet lined with parchment paper.\n"
|
| 375 |
+
]
|
| 376 |
+
},
|
| 377 |
+
"44": {
|
| 378 |
+
"steps": [
|
| 379 |
+
"Preheat oven to 180\u00b0C/350\u00b0F. Add flour, gingerbread spice, cinnamon, salt, and baking powder to a bowl and combine.",
|
| 380 |
+
"In another bowl, beat soft butter, cane sugar and egg for approx. 5 min. until smooth. Stir in applesauce.",
|
| 381 |
+
"Gradually add the dry ingredients and mix into a smooth dough.",
|
| 382 |
+
"Grease loaf pan and line with parchment paper. Transfer dough into loaf pan and bake at 180\u00b0C/350\u00b0F for approx. 50 - 60 min., or until a toothpick inserted into the center comes out clean.",
|
| 383 |
+
"Remove from oven and let cool completely. For the frosting, beat soft butter, confectioner's sugar, cream cheese, and vanilla extract until fluffy.",
|
| 384 |
+
"Unmold cake and spread the frosting on top. Dust with cinnamon."
|
| 385 |
+
],
|
| 386 |
+
"title": "Gingerbread loaf cake",
|
| 387 |
+
"captions": [
|
| 388 |
+
"Close-up view of a bowl containing flour, gingerbread spice, cinnamon, salt, and baking powder, being mixed together.",
|
| 389 |
+
"A woman stirring a bowl of applesauce with a spoon.",
|
| 390 |
+
"A woman adding dry ingredients to a bowl of applesauce.",
|
| 391 |
+
"A woman carefully placing a prepared loaf of dough into a loaf pan, which is then shown in an oven baking at 180\u00b0C/350\u00b0F.",
|
| 392 |
+
"A woman beating a bowl of frosting with a whisk.",
|
| 393 |
+
"A woman spreading frosting on top of a baked loaf cake with a spatula.\n"
|
| 394 |
+
]
|
| 395 |
+
},
|
| 396 |
+
"46": {
|
| 397 |
+
"steps": [
|
| 398 |
+
"Preheat oven to 200\u00b0C/400\u00b0F and line a baking sheet with parchment paper, if needed. Peel carrots and roughy dice. Add to a large mixing bowl along with garlic, olive oil, and cumin and stir to coat.",
|
| 399 |
+
"Add carrot mixture to the prepared baking sheet, transfer to oven, and roast for approx. 20 min. at 200\u00b0C/400\u00b0F until carrots are tender.",
|
| 400 |
+
"Drain chickpeas and reserve the liquid. Transfer carrot mixture, chickpeas, lemon juice, lemon zest, and paprika powder to a food processor and blend until creamy. Add reserved liquid from chickpeas, a little at a time while blending, until smooth and silky in texture. Season with salt and pepper to taste.",
|
| 401 |
+
"Transfer hummus to a serving bowl, drizzle with olive oil, and sprinkle with paprika powder and Ras el Hanout to taste. Cut pita bread into triangles and toast. Serve alongside hummus and"
|
| 402 |
+
],
|
| 403 |
+
"title": "Carrot hummus with pita bread",
|
| 404 |
+
"captions": [
|
| 405 |
+
"Close-up view of hands using a knife to finely chop carrots on a parchment-lined baking sheet.",
|
| 406 |
+
"A spatula smoothly spreading a mixture of chopped carrots onto a baking sheet.",
|
| 407 |
+
"A food processor blending a vibrant mixture of carrots, chickpeas, lemon juice, lemon zest, and paprika powder.",
|
| 408 |
+
"A bowl filled with creamy hummus, topped with a sprinkle of paprika powder and Ras el Hanout.\n"
|
| 409 |
+
]
|
| 410 |
+
},
|
| 411 |
+
"47": {
|
| 412 |
+
"steps": [
|
| 413 |
+
"Prepare the Onion, Habanero Pepper, Tomato, Scallion, and Bell Pepper. Normally bell peppers and scallions are not used like this in its original form is very rustic, but using up the stuff you have in the fridge when you cook reduces waste.",
|
| 414 |
+
"Heat a pan on medium heat, then empty the contents of the Corned Beef Lunch Meat into it and break it apart. The corned beef itself is very fatty, so basically there\u2019s no real need for oil.",
|
| 415 |
+
"Toss everything into the pan with the corned beef and hit it with a dash of Ground Black Pepper and Ketchup. Don\u2019t cover or you\u2019ll risk everything going soggy and into a \u201cmush\u201d. Cook on medium heat while stirring for 5-7 minutes.",
|
| 416 |
+
"Serve with sliced cucumber on the side and some rice. This can also be enjoyed on sandwiches, as a topping for crackers, roti, sliced bread.. even stuffed in pitas."
|
| 417 |
+
],
|
| 418 |
+
"title": "Classic Caribbean Corned Beef",
|
| 419 |
+
"captions": [
|
| 420 |
+
"Close-up view of hands chopping a bell pepper and scallions on a wooden cutting board.",
|
| 421 |
+
"A pan sits on a stovetop, its contents\u2014corned beef\u2014being gently broken apart with a spoon.",
|
| 422 |
+
"A pan sits on a stovetop, its contents\u2014corned beef\u2014being gently broken apart with a spoon.",
|
| 423 |
+
"A bowl filled with a refreshing cucumber salad; a spoon rests inside.\n"
|
| 424 |
+
]
|
| 425 |
+
},
|
| 426 |
+
"50": {
|
| 427 |
+
"steps": [
|
| 428 |
+
"Combine the Frozen Pineapple, Frozen Strawberries, Pear, Frozen Blueberries, and Water in a blender and blend until smooth.",
|
| 429 |
+
"Transfer the slushy fruits to a large punch bowl and add the Sprite just before serving.",
|
| 430 |
+
"Your punch is ready to serve! Scoop into glasses."
|
| 431 |
+
],
|
| 432 |
+
"title": "Sparkling Fruit Slushy",
|
| 433 |
+
"captions": [
|
| 434 |
+
"Blender filled with frozen pineapple, strawberries, pear, blueberries, and water.",
|
| 435 |
+
"Large punch bowl filled with a slushy mixture of fruits and Sprite.",
|
| 436 |
+
"Punch bowl filled with a slushy mixture of fruits and Sprite.\n"
|
| 437 |
+
]
|
| 438 |
+
},
|
| 439 |
+
"51": {
|
| 440 |
+
"steps": [
|
| 441 |
+
"Heat oil in a pan. Add Chili Powder, Ground Black Pepper, Ground Turmeric, Ground Coriander, Salt, and Curry Leaf. Mix well for 5 minutes over a low flame.",
|
| 442 |
+
"Halve the Egg and place them in the masalas. Let it fry for 1 minute.",
|
| 443 |
+
"Flip the eggs carefully without damaging the yolk and roast for another minute. Switch off the flame. Yummy egg fry is ready."
|
| 444 |
+
],
|
| 445 |
+
"title": "Simple Egg Fry",
|
| 446 |
+
"captions": [
|
| 447 |
+
"A pan with chili powder, ground black pepper, ground turmeric, ground coriander, salt, and curry leaf.",
|
| 448 |
+
"Halved eggs frying gently in a pan of spices.",
|
| 449 |
+
"A person flipping eggs in a pan on a stove.\n"
|
| 450 |
+
]
|
| 451 |
+
},
|
| 452 |
+
"54": {
|
| 453 |
+
"steps": [
|
| 454 |
+
"Pre-heat oven to 220\u00b0C/430\u00b0F. Cut sweet potatoes into matchsticks and transfer them to a large bowl. Add cornstarch and toss to coat. Spread sweet potato fries over a baking sheet. Add some oil and smoked ground paprika and toss to coat. Bake for approx. 20 min. or until golden-brown and crisp. Remove from oven and season with salt to taste.",
|
| 455 |
+
"Finely slice white cabbage and transfer to a bowl. Add cashew cream, white balsamic vinegar, coriander, salt, and pepper, and stir to combine. Let sit until serving to marinate.",
|
| 456 |
+
"Add vegan mayonnaise, cinnamon, and chili powder to a small bowl and stir to combine. Refrigerate until serving.",
|
| 457 |
+
"Heat remaining oil in a frying pan. Add oyster mushrooms and fry over medium heat for approx. 8 min. Remove from heat and season with salt to taste.",
|
| 458 |
+
"Spread some ketchup and vegan spicy cinnamon mayonnaise on each toasted white bread slice. Top half of the slices with lamb\u2019s lettuce, sweet potato fries, white cabbage slaw, fried oyster mushrooms, and some sliced red onion. Place remaining white bread slices on top.",
|
| 459 |
+
"This and more delicious recipes can be found in Sebastian Copien\u00b4s cookbook \u201cDie vegane Kochschule\u201c (Christian Verlag)."
|
| 460 |
+
],
|
| 461 |
+
"title": "Winter sandwich with spicy cinnamon mayo",
|
| 462 |
+
"captions": [
|
| 463 |
+
"Woman chopping sweet potatoes into matchsticks, tossing them with cornstarch, and arranging them on a baking sheet with oil and smoked paprika.",
|
| 464 |
+
"Bowl of white cabbage with white balsamic vinegar being poured over it.",
|
| 465 |
+
"Small bowl with vegan mayonnaise, cinnamon, and chili powder being stirred together.",
|
| 466 |
+
"Oyster mushrooms cooking in a frying pan.",
|
| 467 |
+
"Two slices of toasted white bread topped with ketchup, vegan spicy cinnamon mayonnaise, lamb's lettuce, sweet potato fries, white cabbage slaw, fried oyster mushrooms, and sliced red onion.",
|
| 468 |
+
"A cookbook titled \"Die vegane Kochschule\" rests on a wooden table.\n"
|
| 469 |
+
]
|
| 470 |
+
}
|
| 471 |
+
}
|
example.png
ADDED
|
Git LFS Details
|
models/CoSeD/checkpoints/epoch=19-step=140.ckpt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:79988a3d86f30cf7ea8c738b7c195be72d19fc075a8172a06fd239cd20d0ddc1
|
| 3 |
+
size 10531819
|
models/CoSeD/cross_attention.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from BeamDiffusionModel.models.CoSeD.sequence_predictor import SoftAttention
|
| 2 |
+
import torch
|
| 3 |
+
|
| 4 |
+
model = SoftAttention.load_from_checkpoint(
|
| 5 |
+
"./BeamDiffusionModel/models/CoSeD/checkpoints/epoch=19-step=140.ckpt")
|
| 6 |
+
# "/user/home/vcc.ramos/latent_training/sft/reference_training/9q3eu8vi/checkpoints/epoch=7-step=15.ckpt"
|
| 7 |
+
|
| 8 |
+
model.eval()
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def get_softmax(previous_steps_embeddings, previous_images_embeddings, current_steps_embeddings,
|
| 12 |
+
current_images_embeddings):
|
| 13 |
+
previous_steps_tensor = torch.cat(previous_steps_embeddings, dim=0).to("cpu").unsqueeze(0)
|
| 14 |
+
previous_images_tensor = torch.cat(previous_images_embeddings, dim=0).to("cpu").unsqueeze(0)
|
| 15 |
+
current_steps_tensor = torch.cat(current_steps_embeddings).to("cpu").unsqueeze(0)
|
| 16 |
+
current_images_tensor = torch.cat(current_images_embeddings).to("cpu").unsqueeze(0)
|
| 17 |
+
with torch.no_grad():
|
| 18 |
+
softmax, logit = model(current_steps_tensor,
|
| 19 |
+
current_images_tensor,
|
| 20 |
+
previous_steps_tensor,
|
| 21 |
+
previous_images_tensor
|
| 22 |
+
)
|
| 23 |
+
if len(softmax.shape) <= 1:
|
| 24 |
+
return softmax
|
| 25 |
+
# sum and normalize the softmax values
|
| 26 |
+
return torch.sum(softmax, dim=-1) / softmax.shape[-1]
|
models/CoSeD/sequence_predictor.py
ADDED
|
@@ -0,0 +1,675 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
import pickle
|
| 3 |
+
import sys
|
| 4 |
+
|
| 5 |
+
import torch
|
| 6 |
+
from torch import nn, optim
|
| 7 |
+
from torch.utils.data import DataLoader
|
| 8 |
+
import torch.nn.functional as F
|
| 9 |
+
|
| 10 |
+
import lightning as L
|
| 11 |
+
from lightning.pytorch.tuner import Tuner
|
| 12 |
+
from lightning.pytorch.callbacks import LearningRateMonitor
|
| 13 |
+
import wandb
|
| 14 |
+
from pytorch_lightning.loggers import WandbLogger
|
| 15 |
+
from transformers import CLIPTokenizer, CLIPTextModelWithProjection
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class SoftAttention(L.LightningModule):
|
| 20 |
+
def __init__(self, learning_rate=0.001, batch_size=10, unfreeze=0, random_text=False, random_everything=False,
|
| 21 |
+
fixed_text=False, random_images=False):
|
| 22 |
+
super(SoftAttention, self).__init__()
|
| 23 |
+
self.my_optimizer = None
|
| 24 |
+
self.my_scheduler = None
|
| 25 |
+
self.save_hyperparameters()
|
| 26 |
+
self.learning_rate = learning_rate
|
| 27 |
+
self.batch_size = batch_size
|
| 28 |
+
self.frozen = False
|
| 29 |
+
self.unfreeze_epoch = unfreeze
|
| 30 |
+
self.loss_method = torch.nn.CrossEntropyLoss()
|
| 31 |
+
self.train_sum_precision = 0
|
| 32 |
+
self.train_sum_accuracy = 0
|
| 33 |
+
self.train_sum_recall = 0
|
| 34 |
+
self.train_sum_runs = 0
|
| 35 |
+
self.val_sum_precision = 0
|
| 36 |
+
self.val_sum_accuracy = 0
|
| 37 |
+
self.val_sum_recall = 0
|
| 38 |
+
self.val_sum_runs = 0
|
| 39 |
+
|
| 40 |
+
# NETWORK
|
| 41 |
+
# Linear layers to reduce dimensionality
|
| 42 |
+
self.text_reduction = torch.nn.Linear(512, 256)
|
| 43 |
+
self.image_reduction = torch.nn.Linear(512, 256)
|
| 44 |
+
|
| 45 |
+
# Soft attention weights
|
| 46 |
+
self.W_query_text_half_dim = torch.nn.Linear(256, 256)
|
| 47 |
+
self.W_query_image_half_dim = torch.nn.Linear(256, 256)
|
| 48 |
+
self.W_query_text_full_dim = torch.nn.Linear(512, 512)
|
| 49 |
+
self.W_query_image_full_dim = torch.nn.Linear(512, 512)
|
| 50 |
+
|
| 51 |
+
self.W_key_text_half_dim = torch.nn.Linear(256, 256)
|
| 52 |
+
self.W_key_image_half_dim = torch.nn.Linear(256, 256)
|
| 53 |
+
self.W_key_image_full_dim = torch.nn.Linear(512, 512)
|
| 54 |
+
self.W_key_text_full_dim = torch.nn.Linear(512, 512)
|
| 55 |
+
|
| 56 |
+
# TO TEST THE MODEL WITH SAME TEXT
|
| 57 |
+
self.fixed_text = torch.tensor([2.2875e-01, 2.3762e-02, 1.3448e-01, 6.5997e-02, 2.5605e-01,
|
| 58 |
+
-1.6183e-01, 7.1169e-03, -1.6895e+00, 1.8110e-01, 1.7249e-01,
|
| 59 |
+
7.0582e-02, -6.3566e-02, -1.5862e-01, -2.3586e-01, 6.9382e-02,
|
| 60 |
+
9.4649e-02, 6.3127e-01, -4.1287e-02, -4.9883e-02, -2.1821e-01,
|
| 61 |
+
5.8677e-01, -2.5353e-01, 1.4792e-01, 2.2195e-02, -6.8436e-02,
|
| 62 |
+
-1.5512e-01, -9.8894e-02, 6.3377e-02, -2.3078e-01, 9.3588e-02,
|
| 63 |
+
5.2875e-02, -5.1388e-01, -7.0461e-02, 2.4253e-02, -7.8069e-02,
|
| 64 |
+
7.6921e-02, -1.1610e-01, -1.3345e-01, 7.8038e-03, -2.0226e-01,
|
| 65 |
+
1.1381e-01, -9.6335e-02, -2.2195e-02, -6.5028e-02, 1.4025e-01,
|
| 66 |
+
2.6969e-01, -1.0758e-01, 3.6736e-02, 3.2893e-01, -1.9067e-01,
|
| 67 |
+
4.9070e-02, 8.0207e-02, 7.2942e-02, 7.7496e-03, 2.0883e-01,
|
| 68 |
+
1.7339e-01, 1.0072e-01, -1.7874e-01, -4.6898e-02, -6.2682e-02,
|
| 69 |
+
5.9596e-02, 5.2925e-02, 2.4633e-01, -7.2811e-02, -1.4157e-01,
|
| 70 |
+
8.8013e-03, -4.6815e-02, -7.4260e-02, 8.6530e-03, -1.8174e-01,
|
| 71 |
+
1.6101e-01, -4.8832e-02, -5.8030e-02, -3.2518e-02, -6.2896e-02,
|
| 72 |
+
-2.3472e-01, -8.0996e-02, 1.1261e-01, -2.1039e-01, -2.3837e-01,
|
| 73 |
+
-2.6827e-02, -2.3075e-01, -2.2087e-02, 5.4009e-01, 3.7671e-02,
|
| 74 |
+
3.3140e-01, -4.2569e-02, -1.6946e-01, 1.7165e-01, 3.0887e-01,
|
| 75 |
+
4.9847e-02, 1.2438e-02, -2.0701e+00, 2.7104e-01, 1.9001e-01,
|
| 76 |
+
3.1907e-01, -9.1116e-02, -8.3141e-02, 4.5765e-03, -2.5675e-01,
|
| 77 |
+
-2.2119e-02, 3.4949e-02, 2.8192e-01, 7.9688e-02, -2.1810e-01,
|
| 78 |
+
8.1565e-02, 3.3208e-01, -9.1857e-02, -2.1145e-01, -1.6843e-01,
|
| 79 |
+
6.7942e-02, 5.1067e-01, -1.6835e-01, 2.2090e-02, 1.8061e-02,
|
| 80 |
+
-2.1313e-01, 2.6867e-02, -2.2734e-01, 8.4164e-02, -4.7868e-02,
|
| 81 |
+
2.0980e-02, -2.1424e-01, -2.2919e-02, 1.7554e-01, 5.2253e-02,
|
| 82 |
+
-2.2049e-01, 6.9408e-02, 7.0811e-02, -1.1892e-02, -4.7958e-02,
|
| 83 |
+
7.9476e-02, 1.8851e-01, 2.2516e-02, 8.6119e+00, -7.8583e-02,
|
| 84 |
+
1.0218e-01, 1.6675e-01, -4.0961e-01, 4.5291e-02, 7.9783e-02,
|
| 85 |
+
-1.1764e-01, -2.3162e-01, -2.7717e-02, 1.2963e-01, -3.0165e-01,
|
| 86 |
+
-2.1588e-02, -1.2324e-01, 1.9732e-02, -1.9312e-01, -7.1229e-02,
|
| 87 |
+
2.5102e-01, -4.1674e-01, -1.5610e-01, -6.1321e-03, -4.5332e-02,
|
| 88 |
+
6.1500e-02, -1.5942e-01, 3.5142e-01, -2.1119e-01, 4.5057e-02,
|
| 89 |
+
-5.6277e-02, -3.4298e-01, -1.6499e-01, -2.9384e-02, -2.7163e-01,
|
| 90 |
+
6.5339e-03, 2.7674e-02, -1.1302e-01, -2.6373e-02, -1.4370e-01,
|
| 91 |
+
2.1936e-01, 1.3103e-01, 2.5538e-01, 1.9502e-01, -1.5278e-01,
|
| 92 |
+
1.4978e-01, -2.5552e-01, 2.2397e-01, -1.0369e-01, -1.0491e-01,
|
| 93 |
+
5.1112e-01, 2.4879e-01, 7.0940e-02, 1.7351e-01, -3.6831e-02,
|
| 94 |
+
1.5027e-01, -1.9452e-01, 2.0322e-01, 8.5931e-02, -2.8588e-03,
|
| 95 |
+
3.1146e-02, -3.3307e-01, 1.1595e-01, 1.9435e-01, -3.4536e-02,
|
| 96 |
+
2.5245e-01, 4.5388e-02, 2.1197e-02, 4.2232e-02, 4.2436e-02,
|
| 97 |
+
4.9622e-02, -2.0907e-01, 1.2264e-01, -7.3529e-02, -2.1788e-01,
|
| 98 |
+
-1.2429e-01, -8.1422e-02, 1.6572e-01, -6.0989e-02, 8.0322e-02,
|
| 99 |
+
3.3477e-01, -7.2207e-02, -8.8658e-02, -2.4944e-01, 9.9211e-02,
|
| 100 |
+
8.6244e-02, 8.8807e-02, -1.9676e-01, -4.5365e-03, -3.7754e-01,
|
| 101 |
+
-1.7204e-01, -1.3001e-01, 6.4961e-02, -5.8192e-03, 2.4670e-01,
|
| 102 |
+
-8.3591e-02, -3.0810e-01, -3.4549e-02, -1.4452e-01, -5.5416e-02,
|
| 103 |
+
1.0527e-02, 3.1159e-01, -1.3857e-01, -2.2676e-01, 1.4768e-01,
|
| 104 |
+
3.2650e-01, 2.3971e-01, 6.8196e-02, -2.6235e-02, -2.9741e-01,
|
| 105 |
+
4.7721e-02, -1.2859e-02, 2.0340e-01, 1.7823e-02, -1.1337e-01,
|
| 106 |
+
4.4077e-02, -1.3949e-01, 2.9229e-01, 1.7425e-01, -5.0722e-03,
|
| 107 |
+
-6.3722e-02, 1.0181e-01, 2.3344e-02, 2.2200e-01, 3.5022e-02,
|
| 108 |
+
1.5361e-01, -1.0702e-03, 2.9319e-02, 1.8938e-01, -7.2263e-02,
|
| 109 |
+
2.2192e-02, 9.5394e-02, -4.4459e-03, 7.6698e-02, -1.7830e-01,
|
| 110 |
+
1.0213e-01, -8.8493e-02, -1.6439e-01, -1.1085e-01, 1.2938e-01,
|
| 111 |
+
2.3929e-01, -4.9047e-02, -1.2814e-01, -2.1075e-01, 2.4423e-01,
|
| 112 |
+
-4.4565e-02, -5.1225e-02, -4.0214e-02, -1.4033e-01, 6.3284e-02,
|
| 113 |
+
4.7094e-01, -2.6821e-02, 2.1138e-02, 1.1590e-01, -2.0023e-02,
|
| 114 |
+
1.7200e-01, 3.8215e-01, -2.4871e-01, -1.5359e-01, 2.4691e-01,
|
| 115 |
+
1.4904e-01, -1.0636e-01, 2.4185e-01, 1.7119e-03, 1.4618e-01,
|
| 116 |
+
-1.6813e-01, -4.4372e-01, -1.7475e-01, -6.9891e-02, -4.5553e-02,
|
| 117 |
+
9.3102e-02, 1.7686e-02, -1.1781e-01, 6.9423e-02, 1.0211e-02,
|
| 118 |
+
3.2742e-01, 7.5272e-02, 8.5080e-02, -1.7731e-01, 1.4030e-01,
|
| 119 |
+
2.7764e-01, -6.5041e-02, 8.5968e+00, 2.5900e-01, -2.0825e-01,
|
| 120 |
+
9.6241e-02, -1.5257e-01, -3.4269e-01, -1.1251e-01, 3.0549e-01,
|
| 121 |
+
3.1628e-01, 6.1856e-01, 1.5791e-03, 6.5656e-02, 1.8862e-02,
|
| 122 |
+
-7.1927e-02, 1.3239e-01, -1.1126e-01, 1.1135e-02, -3.2411e+00,
|
| 123 |
+
-4.7349e-02, 1.4775e-01, -9.7712e-02, 4.5727e-02, -1.3868e-01,
|
| 124 |
+
2.1260e-01, 1.5465e-01, 1.1308e-01, -8.0110e-02, -1.3123e-01,
|
| 125 |
+
1.8527e-01, -8.6424e-02, -1.9778e-01, -1.3295e-01, -1.5880e-01,
|
| 126 |
+
2.0800e-01, -3.6513e-02, 2.6472e-02, 2.7275e-01, 1.8995e-01,
|
| 127 |
+
-7.7340e-02, 1.2059e-02, 3.5163e-02, 1.5442e-02, 5.1417e-02,
|
| 128 |
+
5.0993e-01, 1.2994e-01, 2.3873e-01, -7.2816e-02, 1.5850e-01,
|
| 129 |
+
-2.0404e-01, -2.2941e-01, 2.3660e-01, 2.0418e-01, 6.7775e-02,
|
| 130 |
+
-3.9195e-01, 3.6655e-01, 1.6498e-01, 6.4065e-02, 4.9579e-02,
|
| 131 |
+
2.8265e-01, -5.9919e-03, 4.0163e-02, 8.9072e-02, 1.5125e-01,
|
| 132 |
+
9.0711e-02, -1.2608e-01, -1.0413e-01, -2.1931e-01, 5.0183e-02,
|
| 133 |
+
-3.4841e-02, -8.1449e-02, -1.1225e-01, -4.5787e-02, -7.8871e-02,
|
| 134 |
+
3.8858e-02, 9.2660e-02, 1.5991e-01, -6.7528e-02, -6.3166e-02,
|
| 135 |
+
-4.7824e-03, -1.3528e-01, 1.4845e-01, 2.0460e-01, -9.3238e-02,
|
| 136 |
+
1.4902e-03, 1.1896e-01, -3.1337e-01, 2.1637e-02, 1.4990e-01,
|
| 137 |
+
-2.1179e-03, -8.1374e-02, -1.0241e-01, -8.0754e-02, -1.4449e-01,
|
| 138 |
+
-1.3549e-01, -7.5588e-02, -8.0083e-02, -1.4114e-01, 2.9467e-03,
|
| 139 |
+
3.5340e-01, -4.3351e-02, 9.6934e-02, 1.3625e-01, 1.3339e-01,
|
| 140 |
+
-1.2059e-02, -1.4325e-01, -2.1202e-01, 3.8758e-02, 2.5965e-01,
|
| 141 |
+
-7.8454e-02, 1.5983e-01, 1.0115e-02, 2.2192e-01, -1.4043e-01,
|
| 142 |
+
6.7966e-02, -1.4672e-01, -1.8846e-01, 1.9488e-01, 1.2942e-01,
|
| 143 |
+
-1.3165e-02, -1.6099e-01, -9.6146e-02, 1.3439e-01, -5.0560e-02,
|
| 144 |
+
8.2779e-02, -2.4827e-01, -7.8047e-02, -3.1163e-01, -1.7481e-01,
|
| 145 |
+
2.1450e-01, -7.6112e-02, -1.9967e-02, 5.7099e-02, 7.7664e-02,
|
| 146 |
+
-7.9647e-02, 3.3941e-02, 2.9551e-02, 1.4231e-01, 2.3480e-02,
|
| 147 |
+
1.5209e-01, -2.0011e-01, 1.1153e-01, 1.2694e-01, 8.7853e-02,
|
| 148 |
+
2.6997e-01, 1.3525e-01, 1.9541e-01, 3.4429e-03, -9.6446e-02,
|
| 149 |
+
7.6708e-02, -3.0698e-02, -1.8507e-01, 2.5645e-01, 2.8182e-01,
|
| 150 |
+
-1.2282e-01, -1.1017e-01, 2.2249e-01, 2.1966e-01, 3.5795e-01,
|
| 151 |
+
1.6279e-01, 1.7276e-01, 2.1410e-01, -3.2499e-01, 5.0327e-02,
|
| 152 |
+
7.9813e-02, -1.5915e-01, -3.6175e-02, 1.4376e-01, 2.9565e-01,
|
| 153 |
+
6.9097e-02, -8.0661e-01, 4.9966e-02, 6.2506e-02, 1.8852e-02,
|
| 154 |
+
-8.6921e-02, 6.0899e-02, 2.2442e-01, -1.4272e-01, -4.0656e-04,
|
| 155 |
+
-1.2531e-01, 1.5240e-01, -6.8841e-02, 4.2114e-01, -4.4379e-02,
|
| 156 |
+
-3.5105e-02, 1.4931e-01, -8.3358e-02, -1.0498e-01, 1.4575e-01,
|
| 157 |
+
-1.6491e-01, 4.7820e-02, 2.5958e-01, 1.1974e-01, 1.8271e-01,
|
| 158 |
+
1.7439e-02, -1.5855e-01, -9.0135e-02, -2.6199e-01, -2.5709e-01,
|
| 159 |
+
6.3203e-03, 7.5823e-02])
|
| 160 |
+
|
| 161 |
+
self.random_text_flag = random_text
|
| 162 |
+
self.random_everything_flag = random_everything
|
| 163 |
+
self.fixed_text_flag = fixed_text
|
| 164 |
+
self.random_image_flag = random_images
|
| 165 |
+
|
| 166 |
+
# Weight Stacks
|
| 167 |
+
self.W_query = {
|
| 168 |
+
"multimodal": [self.text_reduction, self.image_reduction, self.W_query_text_half_dim,
|
| 169 |
+
self.W_query_image_half_dim],
|
| 170 |
+
"image": [self.W_query_image_full_dim],
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
self.W_key = {
|
| 174 |
+
"multimodal": [self.text_reduction, self.image_reduction, self.W_key_text_half_dim,
|
| 175 |
+
self.W_key_image_half_dim],
|
| 176 |
+
"image": [self.W_key_image_full_dim]
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
def weight_pass(self, query_text, query_image, key_text, key_image):
|
| 180 |
+
inference_functions = [
|
| 181 |
+
(True, True, True, True), # Input: text and image Context: text and image
|
| 182 |
+
(False, True, False, True), # Input: image Context: image
|
| 183 |
+
(False, True, True, True) # Input: image Context: text and image
|
| 184 |
+
]
|
| 185 |
+
|
| 186 |
+
if None in (query_image, key_image):
|
| 187 |
+
raise ValueError("Query and Key image cannot be None")
|
| 188 |
+
|
| 189 |
+
if (query_text is not None, query_image is not None, key_text is not None,
|
| 190 |
+
key_image is not None) in inference_functions:
|
| 191 |
+
query = self._queries_inference(query_text, query_image)
|
| 192 |
+
key = self._keys_inference(key_text, key_image)
|
| 193 |
+
return query, key
|
| 194 |
+
else:
|
| 195 |
+
raise ValueError("Invalid input")
|
| 196 |
+
|
| 197 |
+
def _queries_inference(self, query_text, query_image):
|
| 198 |
+
if query_text is None:
|
| 199 |
+
output = self.W_query_image_full_dim(query_image)
|
| 200 |
+
elif query_image is None:
|
| 201 |
+
raise ValueError("Query image cannot be None")
|
| 202 |
+
else:
|
| 203 |
+
text_reduction = self.text_reduction(query_text)
|
| 204 |
+
image_reduction = self.image_reduction(query_image)
|
| 205 |
+
query_text_half_dim = self.W_query_text_half_dim(text_reduction)
|
| 206 |
+
query_image_half_dim = self.W_query_image_half_dim(image_reduction)
|
| 207 |
+
output = torch.cat((query_text_half_dim, query_image_half_dim), dim=-1)
|
| 208 |
+
return output
|
| 209 |
+
|
| 210 |
+
def _keys_inference(self, key_text, key_image):
|
| 211 |
+
if key_text is None:
|
| 212 |
+
output = self.W_key_image_full_dim(key_image)
|
| 213 |
+
elif key_image is None:
|
| 214 |
+
raise ValueError("Key image cannot be None")
|
| 215 |
+
else:
|
| 216 |
+
text_reduction = self.text_reduction(key_text)
|
| 217 |
+
image_reduction = self.image_reduction(key_image)
|
| 218 |
+
key_text_half_dim = self.W_key_text_half_dim(text_reduction)
|
| 219 |
+
key_image_half_dim = self.W_key_image_half_dim(image_reduction)
|
| 220 |
+
output = torch.cat((key_text_half_dim, key_image_half_dim), dim=-1)
|
| 221 |
+
return output
|
| 222 |
+
|
| 223 |
+
def forward(self, query_text, query_image, key_text, key_image):
|
| 224 |
+
|
| 225 |
+
query_text = query_text.to(self.device)
|
| 226 |
+
query_image = query_image.to(self.device)
|
| 227 |
+
key_text = key_text.to(self.device)
|
| 228 |
+
key_image = key_image.to(self.device)
|
| 229 |
+
query, key = self.weight_pass(query_text, query_image, key_text, key_image)
|
| 230 |
+
|
| 231 |
+
d_k = key.size()[-1] # Get the size of the key
|
| 232 |
+
|
| 233 |
+
key_transposed = key.transpose(1, 2)
|
| 234 |
+
logits = torch.matmul(query, key_transposed) / math.sqrt(d_k)
|
| 235 |
+
logits = logits.squeeze()
|
| 236 |
+
|
| 237 |
+
if len(logits.shape) <= 2:
|
| 238 |
+
softmax = F.softmax(logits, dim=0)
|
| 239 |
+
else:
|
| 240 |
+
softmax = F.softmax(logits, dim=1)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
return softmax, logits
|
| 244 |
+
|
| 245 |
+
def training_step(self, train_batch, batch_idx):
|
| 246 |
+
|
| 247 |
+
if self.current_epoch == 0 and not self.frozen and self.unfreeze_epoch != 0:
|
| 248 |
+
print("Freezing....................................................")
|
| 249 |
+
for param in self.image_reduction.parameters():
|
| 250 |
+
param.requires_grad = False
|
| 251 |
+
self.frozen = True
|
| 252 |
+
|
| 253 |
+
if self.current_epoch == self.unfreeze_epoch and self.frozen:
|
| 254 |
+
print("Unfreezing....................................................")
|
| 255 |
+
for param in self.image_reduction.parameters():
|
| 256 |
+
param.requires_grad = True
|
| 257 |
+
self.frozen = False
|
| 258 |
+
|
| 259 |
+
# Unpack the batch data
|
| 260 |
+
queries = train_batch['queries']
|
| 261 |
+
keys = train_batch['keys']
|
| 262 |
+
real_labels = train_batch['real_index']
|
| 263 |
+
|
| 264 |
+
keys_text = []
|
| 265 |
+
keys_image = []
|
| 266 |
+
for batch in keys:
|
| 267 |
+
temp_key_text = []
|
| 268 |
+
temp_key_image = []
|
| 269 |
+
|
| 270 |
+
for key_text, key_image in batch:
|
| 271 |
+
temp_key_text.append(key_text)
|
| 272 |
+
temp_key_image.append(key_image)
|
| 273 |
+
keys_text.append(torch.stack(temp_key_text))
|
| 274 |
+
keys_image.append(torch.stack(temp_key_image))
|
| 275 |
+
|
| 276 |
+
queries_text = []
|
| 277 |
+
queries_image = []
|
| 278 |
+
for batch in queries:
|
| 279 |
+
temp_query_text = []
|
| 280 |
+
temp_query_image = []
|
| 281 |
+
for query_text, query_image in batch:
|
| 282 |
+
temp_query_text.append(query_text)
|
| 283 |
+
temp_query_image.append(query_image)
|
| 284 |
+
queries_text.append(torch.stack(temp_query_text))
|
| 285 |
+
queries_image.append(torch.stack(temp_query_image))
|
| 286 |
+
|
| 287 |
+
queries_text = torch.stack(queries_text)
|
| 288 |
+
queries_image = torch.stack(queries_image)
|
| 289 |
+
keys_text = torch.stack(keys_text)
|
| 290 |
+
keys_image = torch.stack(keys_image)
|
| 291 |
+
|
| 292 |
+
if self.fixed_text_flag:
|
| 293 |
+
print("Fixed text flag")
|
| 294 |
+
queries_text_shape = queries_text.shape
|
| 295 |
+
keys_text_shape = keys_text.shape
|
| 296 |
+
queries_text = self.fixed_text.expand(*queries_text_shape).to(queries_text.device)
|
| 297 |
+
keys_text = self.fixed_text.expand(*keys_text_shape).to(keys_text.device)
|
| 298 |
+
|
| 299 |
+
if self.random_text_flag:
|
| 300 |
+
print("Random text flag")
|
| 301 |
+
old_queries_text = queries_text.clone()
|
| 302 |
+
old_keys_text = keys_text.clone()
|
| 303 |
+
queries_text = torch.randn(queries_text.shape).to(queries_text.device)
|
| 304 |
+
keys_text = torch.randn(keys_text.shape).to(keys_text.device)
|
| 305 |
+
if torch.equal(queries_text, old_queries_text):
|
| 306 |
+
print("Queries text are equal")
|
| 307 |
+
if torch.equal(keys_text, old_keys_text):
|
| 308 |
+
print("Keys text are equal")
|
| 309 |
+
|
| 310 |
+
if self.random_image_flag:
|
| 311 |
+
print("Random image flag")
|
| 312 |
+
old_queries_image = queries_image.clone()
|
| 313 |
+
old_keys_image = keys_image.clone()
|
| 314 |
+
queries_image = torch.randn(queries_image.shape).to(queries_image.device)
|
| 315 |
+
keys_image = torch.randn(keys_image.shape).to(keys_image.device)
|
| 316 |
+
if torch.equal(queries_image, old_queries_image):
|
| 317 |
+
print("Queries image are equal")
|
| 318 |
+
if torch.equal(keys_image, old_keys_image):
|
| 319 |
+
print("Keys image are equal")
|
| 320 |
+
|
| 321 |
+
if self.random_everything_flag:
|
| 322 |
+
print("Random everything flag")
|
| 323 |
+
old_queries_text = queries_text.clone()
|
| 324 |
+
old_keys_text = keys_text.clone()
|
| 325 |
+
old_queries_image = queries_image.clone()
|
| 326 |
+
old_keys_image = keys_image.clone()
|
| 327 |
+
queries_text = torch.randn(queries_text.shape).to(queries_text.device)
|
| 328 |
+
keys_text = torch.randn(keys_text.shape).to(keys_text.device)
|
| 329 |
+
queries_image = torch.randn(queries_image.shape).to(queries_image.device)
|
| 330 |
+
keys_image = torch.randn(keys_image.shape).to(keys_image.device)
|
| 331 |
+
if torch.equal(queries_text, old_queries_text):
|
| 332 |
+
print("Queries text are equal")
|
| 333 |
+
if torch.equal(keys_text, old_keys_text):
|
| 334 |
+
print("Keys text are equal")
|
| 335 |
+
if torch.equal(queries_image, old_queries_image):
|
| 336 |
+
print("Queries image are equal")
|
| 337 |
+
if torch.equal(keys_image, old_keys_image):
|
| 338 |
+
print("Keys image are equal")
|
| 339 |
+
|
| 340 |
+
# Forward pass
|
| 341 |
+
softmax, logits = self.forward(queries_text, queries_image, keys_text, keys_image)
|
| 342 |
+
|
| 343 |
+
softmax = softmax.squeeze()
|
| 344 |
+
real_labels = real_labels.squeeze()
|
| 345 |
+
logits = logits.squeeze()
|
| 346 |
+
real_labels = real_labels.float()
|
| 347 |
+
|
| 348 |
+
if real_labels.dim() < 3:
|
| 349 |
+
real_labels = real_labels.unsqueeze(0)
|
| 350 |
+
softmax = softmax.unsqueeze(0)
|
| 351 |
+
logits = logits.unsqueeze(0)
|
| 352 |
+
|
| 353 |
+
temp_real_labels = []
|
| 354 |
+
temp_logits = []
|
| 355 |
+
global_padding = 0
|
| 356 |
+
for batch_l, batch_r in zip(logits, real_labels):
|
| 357 |
+
padding = torch.nonzero(batch_r[0] == -100)
|
| 358 |
+
if padding.nelement() == 0:
|
| 359 |
+
temp_real_labels.append(batch_r)
|
| 360 |
+
temp_logits.append(batch_l)
|
| 361 |
+
continue
|
| 362 |
+
global_padding = global_padding + padding.nelement()
|
| 363 |
+
padding_index = padding[0]
|
| 364 |
+
temp_r = batch_r.clone()
|
| 365 |
+
temp_r[:, padding_index:] = 0
|
| 366 |
+
temp_l = batch_l.clone()
|
| 367 |
+
temp_l[:, padding_index:] = -100
|
| 368 |
+
temp_real_labels.append(temp_r)
|
| 369 |
+
temp_logits.append(temp_l)
|
| 370 |
+
|
| 371 |
+
for_loss_real_labels = torch.stack(temp_real_labels).float()
|
| 372 |
+
for_loss_logits = torch.stack(temp_logits)
|
| 373 |
+
loss = self.loss_method(for_loss_logits.mT, for_loss_real_labels.mT)
|
| 374 |
+
|
| 375 |
+
batched_precision = []
|
| 376 |
+
batched_accuracy = []
|
| 377 |
+
batched_recall = []
|
| 378 |
+
|
| 379 |
+
for batch_s, batch_r in zip(softmax, real_labels):
|
| 380 |
+
padding = torch.nonzero(batch_r[0] == -100)
|
| 381 |
+
if padding.nelement() > 0:
|
| 382 |
+
padding_index = padding[0]
|
| 383 |
+
batch_r = batch_r[:, :padding_index]
|
| 384 |
+
batch_s = batch_s[:, :padding_index]
|
| 385 |
+
max_indices = batch_s.argmax(dim=0)
|
| 386 |
+
# print("Max indices: ", max_indices)
|
| 387 |
+
target_index = batch_r.argmax(dim=0)
|
| 388 |
+
# print("Target index: ", target_index)
|
| 389 |
+
subtraction = max_indices - target_index
|
| 390 |
+
# print("Subtraction: ", subtraction)
|
| 391 |
+
different_values = torch.count_nonzero(subtraction)
|
| 392 |
+
# print("Different values: ", different_values)
|
| 393 |
+
# print("Sample size: ", target_index.shape)
|
| 394 |
+
# print("Len target index: ", len(target_index))
|
| 395 |
+
samples = batch_s.shape[1] * batch_s.shape[0]
|
| 396 |
+
|
| 397 |
+
TP = len(target_index) - different_values
|
| 398 |
+
FP = different_values
|
| 399 |
+
FN = different_values
|
| 400 |
+
TN = samples - TP - FP - FN
|
| 401 |
+
|
| 402 |
+
precision = TP / (TP + FP)
|
| 403 |
+
accuracy = (TP + TN) / samples
|
| 404 |
+
recall = TP / (TP + FN)
|
| 405 |
+
|
| 406 |
+
batched_precision.append(precision.item())
|
| 407 |
+
batched_accuracy.append(accuracy.item())
|
| 408 |
+
batched_recall.append(recall.item())
|
| 409 |
+
|
| 410 |
+
precision = sum(batched_precision) / len(batched_precision)
|
| 411 |
+
accuracy = sum(batched_accuracy) / len(batched_accuracy)
|
| 412 |
+
recall = sum(batched_recall) / len(batched_recall)
|
| 413 |
+
|
| 414 |
+
self.train_sum_precision += precision
|
| 415 |
+
self.train_sum_accuracy += accuracy
|
| 416 |
+
self.train_sum_recall += recall
|
| 417 |
+
self.train_sum_runs += 1
|
| 418 |
+
self.log("train_loss", loss, on_epoch=True, on_step=False, prog_bar=True, logger=True)
|
| 419 |
+
self.log("train_precision", precision, on_epoch=True, on_step=False, prog_bar=True, logger=True)
|
| 420 |
+
self.log("train_accuracy", accuracy, on_epoch=True, on_step=False, prog_bar=True, logger=True)
|
| 421 |
+
self.log("train_recall", recall, on_epoch=True, on_step=False, prog_bar=True, logger=True)
|
| 422 |
+
|
| 423 |
+
return loss
|
| 424 |
+
|
| 425 |
+
def on_train_epoch_end(self) -> None:
|
| 426 |
+
self.log("train_precision_epoch", self.train_sum_precision / self.train_sum_runs)
|
| 427 |
+
self.log("train_accuracy_epoch", self.train_sum_accuracy / self.train_sum_runs)
|
| 428 |
+
self.log("train_recall_epoch", self.train_sum_recall / self.train_sum_runs)
|
| 429 |
+
self.train_sum_precision = 0
|
| 430 |
+
self.train_sum_accuracy = 0
|
| 431 |
+
self.train_sum_recall = 0
|
| 432 |
+
self.train_sum_runs = 0
|
| 433 |
+
|
| 434 |
+
def configure_optimizers(self):
|
| 435 |
+
self.my_optimizer = torch.optim.Adam(params=self.parameters(), lr=self.learning_rate)
|
| 436 |
+
optimizer = self.my_optimizer
|
| 437 |
+
"""self.my_scheduler = torch.optim.lr_scheduler.CyclicLR(self.my_optimizer, base_lr=0.01, max_lr=0.05,step_size_up=100,cycle_momentum=False)
|
| 438 |
+
scheduler = {
|
| 439 |
+
'scheduler': self.my_scheduler,
|
| 440 |
+
'interval': 'step',
|
| 441 |
+
'frequency': 1,
|
| 442 |
+
'name': 'learning_rate'
|
| 443 |
+
}"""
|
| 444 |
+
return [optimizer]
|
| 445 |
+
|
| 446 |
+
def validation_step(self, val_batch, batch_idx):
|
| 447 |
+
# Unpack the batch data
|
| 448 |
+
queries = val_batch['queries']
|
| 449 |
+
keys = val_batch['keys']
|
| 450 |
+
real_labels = val_batch['real_index']
|
| 451 |
+
|
| 452 |
+
keys_text = []
|
| 453 |
+
keys_image = []
|
| 454 |
+
for batch in keys:
|
| 455 |
+
temp_key_text = []
|
| 456 |
+
temp_key_image = []
|
| 457 |
+
|
| 458 |
+
for key_text, key_image in batch:
|
| 459 |
+
temp_key_text.append(key_text)
|
| 460 |
+
temp_key_image.append(key_image)
|
| 461 |
+
keys_text.append(torch.stack(temp_key_text))
|
| 462 |
+
keys_image.append(torch.stack(temp_key_image))
|
| 463 |
+
|
| 464 |
+
queries_text = []
|
| 465 |
+
queries_image = []
|
| 466 |
+
for batch in queries:
|
| 467 |
+
temp_query_text = []
|
| 468 |
+
temp_query_image = []
|
| 469 |
+
for query_text, query_image in batch:
|
| 470 |
+
temp_query_text.append(query_text)
|
| 471 |
+
temp_query_image.append(query_image)
|
| 472 |
+
queries_text.append(torch.stack(temp_query_text))
|
| 473 |
+
queries_image.append(torch.stack(temp_query_image))
|
| 474 |
+
|
| 475 |
+
queries_text = torch.stack(queries_text)
|
| 476 |
+
queries_image = torch.stack(queries_image)
|
| 477 |
+
keys_text = torch.stack(keys_text)
|
| 478 |
+
keys_image = torch.stack(keys_image)
|
| 479 |
+
|
| 480 |
+
# Forward pass
|
| 481 |
+
softmax, logits = self.forward(queries_text, queries_image, keys_text, keys_image)
|
| 482 |
+
|
| 483 |
+
softmax = softmax.squeeze()
|
| 484 |
+
real_labels = real_labels.squeeze()
|
| 485 |
+
|
| 486 |
+
if real_labels.dim() < 3:
|
| 487 |
+
real_labels = real_labels.unsqueeze(0)
|
| 488 |
+
softmax = softmax.unsqueeze(0)
|
| 489 |
+
logits = logits.unsqueeze(0)
|
| 490 |
+
|
| 491 |
+
temp_real_labels = []
|
| 492 |
+
temp_logits = []
|
| 493 |
+
for batch_l, batch_r in zip(logits, real_labels):
|
| 494 |
+
padding = torch.nonzero(batch_r[0] == -100)
|
| 495 |
+
if padding.nelement() == 0:
|
| 496 |
+
continue
|
| 497 |
+
padding_index = padding[0]
|
| 498 |
+
temp_r = batch_r.clone()
|
| 499 |
+
temp_r[:, padding_index:] = 0
|
| 500 |
+
temp_l = batch_l.clone()
|
| 501 |
+
temp_l[:, padding_index:] = -100
|
| 502 |
+
temp_real_labels.append(temp_r)
|
| 503 |
+
temp_logits.append(temp_l)
|
| 504 |
+
|
| 505 |
+
if padding.nelement() > 0:
|
| 506 |
+
for_loss_real_labels = torch.stack(temp_real_labels).float()
|
| 507 |
+
for_loss_logits = torch.stack(temp_logits)
|
| 508 |
+
loss = self.loss_method(for_loss_logits.mT, for_loss_real_labels.mT)
|
| 509 |
+
else:
|
| 510 |
+
loss = self.loss_method(logits.mT, real_labels.mT)
|
| 511 |
+
|
| 512 |
+
if loss < 0:
|
| 513 |
+
print("Padding: ", padding.nelement())
|
| 514 |
+
print("Loss: ", loss)
|
| 515 |
+
print("Logits: ", logits)
|
| 516 |
+
print("Real labels: ", real_labels)
|
| 517 |
+
exit()
|
| 518 |
+
|
| 519 |
+
batched_precision = []
|
| 520 |
+
batched_accuracy = []
|
| 521 |
+
batched_recall = []
|
| 522 |
+
for batch_s, batch_r in zip(softmax, real_labels):
|
| 523 |
+
padding = torch.nonzero(batch_r[0] == -100)
|
| 524 |
+
if padding.nelement() > 0:
|
| 525 |
+
padding_index = padding[0]
|
| 526 |
+
batch_r = batch_r[:, :padding_index]
|
| 527 |
+
batch_s = batch_s[:, :padding_index]
|
| 528 |
+
max_indices = batch_s.argmax(dim=0)
|
| 529 |
+
# print("Max indices: ", max_indices)
|
| 530 |
+
target_index = batch_r.argmax(dim=0)
|
| 531 |
+
# print("Target index: ", target_index)
|
| 532 |
+
subtraction = max_indices - target_index
|
| 533 |
+
# print("Subtraction: ", subtraction)
|
| 534 |
+
different_values = torch.count_nonzero(subtraction)
|
| 535 |
+
# print("Different values: ", different_values)
|
| 536 |
+
# print("Sample size: ", target_index.shape)
|
| 537 |
+
# print("Len target index: ", len(target_index))
|
| 538 |
+
samples = batch_s.shape[1] * batch_s.shape[0]
|
| 539 |
+
TP = len(target_index) - different_values
|
| 540 |
+
FP = different_values
|
| 541 |
+
FN = different_values
|
| 542 |
+
TN = samples - TP - FP - FN
|
| 543 |
+
|
| 544 |
+
precision = TP / (TP + FP)
|
| 545 |
+
accuracy = (TP + TN) / samples
|
| 546 |
+
recall = TP / (TP + FN)
|
| 547 |
+
|
| 548 |
+
batched_precision.append(precision.item())
|
| 549 |
+
batched_accuracy.append(accuracy.item())
|
| 550 |
+
batched_recall.append(recall.item())
|
| 551 |
+
|
| 552 |
+
precision = sum(batched_precision) / len(batched_precision)
|
| 553 |
+
accuracy = sum(batched_accuracy) / len(batched_accuracy)
|
| 554 |
+
recall = sum(batched_recall) / len(batched_recall)
|
| 555 |
+
self.val_sum_precision += precision
|
| 556 |
+
self.val_sum_accuracy += accuracy
|
| 557 |
+
self.val_sum_recall += recall
|
| 558 |
+
self.val_sum_runs += 1
|
| 559 |
+
self.log("val_loss", loss, on_epoch=True, on_step=False, prog_bar=True, logger=True)
|
| 560 |
+
self.log("val_precision", precision, on_epoch=True, on_step=False, prog_bar=True, logger=True)
|
| 561 |
+
self.log("val_accuracy", accuracy, on_epoch=True, on_step=False, prog_bar=True, logger=True)
|
| 562 |
+
self.log("val_recall", recall, on_epoch=True, on_step=False, prog_bar=True, logger=True)
|
| 563 |
+
|
| 564 |
+
def on_validation_epoch_end(self) -> None:
|
| 565 |
+
self.log("val_precision_epoch", self.val_sum_precision / self.val_sum_runs)
|
| 566 |
+
self.log("val_accuracy_epoch", self.val_sum_accuracy / self.val_sum_runs)
|
| 567 |
+
self.log("val_recall_epoch", self.val_sum_recall / self.val_sum_runs)
|
| 568 |
+
self.val_sum_precision = 0
|
| 569 |
+
self.val_sum_accuracy = 0
|
| 570 |
+
self.val_sum_recall = 0
|
| 571 |
+
self.val_sum_runs = 0
|
| 572 |
+
|
| 573 |
+
|
| 574 |
+
if __name__ == '__main__':
|
| 575 |
+
|
| 576 |
+
if len(sys.argv) > 1:
|
| 577 |
+
print("Using arguments")
|
| 578 |
+
batch_size = int(sys.argv[1])
|
| 579 |
+
learning_rate = float(sys.argv[2])
|
| 580 |
+
epochs = int(sys.argv[3])
|
| 581 |
+
if sys.argv[4] == "True":
|
| 582 |
+
wandb_flag = True
|
| 583 |
+
else:
|
| 584 |
+
wandb_flag = False
|
| 585 |
+
if sys.argv[5] == "True":
|
| 586 |
+
find_lr = True
|
| 587 |
+
else:
|
| 588 |
+
find_lr = False
|
| 589 |
+
unfreeze = int(sys.argv[6])
|
| 590 |
+
|
| 591 |
+
else:
|
| 592 |
+
print("Using default values")
|
| 593 |
+
batch_size = 500
|
| 594 |
+
learning_rate = 0.01
|
| 595 |
+
epochs = 50
|
| 596 |
+
wandb_flag = True
|
| 597 |
+
find_lr = False
|
| 598 |
+
unfreeze = 10
|
| 599 |
+
random_text = False
|
| 600 |
+
random_everything = False
|
| 601 |
+
random_images = False
|
| 602 |
+
fixed_text = False
|
| 603 |
+
|
| 604 |
+
print("Batch size: ", batch_size)
|
| 605 |
+
print("Learning rate: ", learning_rate)
|
| 606 |
+
print("Epochs: ", epochs)
|
| 607 |
+
print("Wandb flag: ", wandb_flag)
|
| 608 |
+
print("Find lr: ", find_lr)
|
| 609 |
+
print("Unfreeze: ", unfreeze)
|
| 610 |
+
|
| 611 |
+
train_path = "./recipe_dataset_3500_real_1.pkl"
|
| 612 |
+
val_path = "./recipe_dataset_3500_real_2.pkl"
|
| 613 |
+
train = pickle.load(open(train_path, "rb"))
|
| 614 |
+
val = pickle.load(open(val_path, "rb"))
|
| 615 |
+
|
| 616 |
+
if "wrong" in train_path and "wrong" in val_path:
|
| 617 |
+
print("Using dataset with false positives")
|
| 618 |
+
string_wrong = "WRONG_"
|
| 619 |
+
elif "wrong" in train_path or "wrong" in val_path:
|
| 620 |
+
raise ValueError("One of the datasets is wrong")
|
| 621 |
+
else:
|
| 622 |
+
print("Using normal dataset")
|
| 623 |
+
string_wrong = ""
|
| 624 |
+
if random_text:
|
| 625 |
+
string_wrong += "RANDOM_TEXT_"
|
| 626 |
+
elif random_everything:
|
| 627 |
+
string_wrong += "RANDOM_EVERYTHING_"
|
| 628 |
+
elif random_images:
|
| 629 |
+
string_wrong += "RANDOM_IMAGES_"
|
| 630 |
+
elif fixed_text:
|
| 631 |
+
string_wrong += "FIXED_TEXT_"
|
| 632 |
+
|
| 633 |
+
|
| 634 |
+
|
| 635 |
+
# remove fields that are not needed
|
| 636 |
+
for batch in train:
|
| 637 |
+
batch.pop('ids_queries')
|
| 638 |
+
batch.pop('ids_keys')
|
| 639 |
+
|
| 640 |
+
for batch in val:
|
| 641 |
+
batch.pop('ids_queries')
|
| 642 |
+
batch.pop('ids_keys')
|
| 643 |
+
|
| 644 |
+
train_dataset = DataLoader(train, num_workers=0, shuffle=False, batch_size=batch_size)
|
| 645 |
+
print("Train dataset size:", len(train_dataset))
|
| 646 |
+
|
| 647 |
+
val_dataset = DataLoader(val, num_workers=0, shuffle=False, batch_size=batch_size)
|
| 648 |
+
print("Val dataset size:", len(val_dataset))
|
| 649 |
+
|
| 650 |
+
model = SoftAttention(learning_rate=learning_rate, batch_size=batch_size, unfreeze=unfreeze,
|
| 651 |
+
random_text=random_text, random_everything=random_everything, fixed_text=fixed_text,
|
| 652 |
+
random_images=random_images)
|
| 653 |
+
|
| 654 |
+
lr_monitor = LearningRateMonitor(logging_interval='step')
|
| 655 |
+
if wandb_flag:
|
| 656 |
+
run_name = f"{string_wrong}MORE_RECIPES_{len(train_dataset)}_batch_{batch_size}_lr_{learning_rate}_epochs_{epochs}_unfreeze_{unfreeze}"
|
| 657 |
+
wandb_logger = WandbLogger(project='reference_training', name=run_name, log_model="all")
|
| 658 |
+
wandb_logger.experiment.config["batch_size"] = batch_size
|
| 659 |
+
wandb_logger.experiment.config["max_epochs"] = epochs
|
| 660 |
+
wandb_logger.experiment.config["learning_rate"] = learning_rate
|
| 661 |
+
|
| 662 |
+
trainer = L.Trainer(max_epochs=epochs, detect_anomaly=False, logger=wandb_logger, callbacks=[lr_monitor])
|
| 663 |
+
else:
|
| 664 |
+
trainer = L.Trainer(max_epochs=epochs, default_root_dir="./", callbacks=[lr_monitor])
|
| 665 |
+
|
| 666 |
+
if find_lr:
|
| 667 |
+
tuner = Tuner(trainer)
|
| 668 |
+
lr_finder = tuner.lr_find(model, train_dataloaders=train_dataset, val_dataloaders=val_dataset)
|
| 669 |
+
print(lr_finder.suggestion())
|
| 670 |
+
else:
|
| 671 |
+
trainer.fit(model, train_dataloaders=train_dataset, val_dataloaders=val_dataset)
|
| 672 |
+
# trainer.fit(model, train_dataloaders=train_dataset)
|
| 673 |
+
|
| 674 |
+
if wandb_flag:
|
| 675 |
+
wandb.finish()
|
models/clip/clip.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import AutoTokenizer, AutoProcessor, CLIPModel
|
| 2 |
+
from PIL import Image
|
| 3 |
+
import torch
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class Clip():
|
| 7 |
+
_instance = None
|
| 8 |
+
|
| 9 |
+
def __new__(cls, *args, **kwargs):
|
| 10 |
+
if not cls._instance:
|
| 11 |
+
cls._instance = super(Clip, cls).__new__(cls, *args, **kwargs)
|
| 12 |
+
return cls._instance
|
| 13 |
+
|
| 14 |
+
def __init__(self):
|
| 15 |
+
if not hasattr(self, 'initialized'): # To ensure __init__ is only called once
|
| 16 |
+
self.processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 17 |
+
self.tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
|
| 18 |
+
self.model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32").to("cuda")
|
| 19 |
+
self.initialized = True
|
| 20 |
+
|
| 21 |
+
def get_model(self):
|
| 22 |
+
return self.model
|
| 23 |
+
|
| 24 |
+
def get_preprocess(self):
|
| 25 |
+
return self.processor
|
| 26 |
+
|
| 27 |
+
def get_tokenizer(self):
|
| 28 |
+
return self.tokenizer
|
| 29 |
+
|
| 30 |
+
def similarity(self, text, image_or_images):
|
| 31 |
+
text_embedding = self.generate_embedding(text)
|
| 32 |
+
image_embeddings = self.generate_embedding(image_or_images)
|
| 33 |
+
|
| 34 |
+
if isinstance(image_embeddings, torch.Tensor):
|
| 35 |
+
# Single image case
|
| 36 |
+
similarity = (text_embedding @ image_embeddings.T)
|
| 37 |
+
else:
|
| 38 |
+
# Multiple images case, image_embeddings is a list of tensors
|
| 39 |
+
similarity = torch.stack([(text_embedding @ image_embedding.T) for image_embedding in image_embeddings])
|
| 40 |
+
# apply softmax to get the similarity score
|
| 41 |
+
similarity = torch.nn.functional.softmax(similarity, dim=0)
|
| 42 |
+
return similarity
|
| 43 |
+
|
| 44 |
+
def generate_embedding(self, data):
|
| 45 |
+
if isinstance(data, Image.Image):
|
| 46 |
+
image_processed = self.processor(images=data, return_tensors="pt").to("cuda")
|
| 47 |
+
image_embedding = self.model.get_image_features(**image_processed)
|
| 48 |
+
return image_embedding
|
| 49 |
+
|
| 50 |
+
elif isinstance(data, list) and all(isinstance(img, Image.Image) for img in data):
|
| 51 |
+
# Multiple images case
|
| 52 |
+
image_embeddings = []
|
| 53 |
+
for img in data:
|
| 54 |
+
image_processed = self.processor(images=img, return_tensors="pt").to("cuda")
|
| 55 |
+
image_embedding = self.model.get_image_features(**image_processed)
|
| 56 |
+
image_embeddings.append(image_embedding)
|
| 57 |
+
return image_embeddings
|
| 58 |
+
|
| 59 |
+
elif isinstance(data, str):
|
| 60 |
+
data = data[0:77]
|
| 61 |
+
text = self.tokenizer(data, return_tensors="pt").to("cuda")
|
| 62 |
+
text_embedding = self.model.get_text_features(**text)
|
| 63 |
+
return text_embedding
|
| 64 |
+
|
| 65 |
+
clip = Clip()
|
models/diffusionModel/Latents_Singleton.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from typing import List
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class Singleton(type):
|
| 6 |
+
_instances = {}
|
| 7 |
+
|
| 8 |
+
def __call__(cls, *args, **kwargs):
|
| 9 |
+
if cls not in cls._instances:
|
| 10 |
+
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
|
| 11 |
+
return cls._instances[cls]
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class Latents(metaclass=Singleton):
|
| 15 |
+
def __init__(self) -> None:
|
| 16 |
+
self.history: List[torch.FloatTensor] = []
|
| 17 |
+
|
| 18 |
+
def is_empty(self) -> bool:
|
| 19 |
+
return self.history is None
|
| 20 |
+
|
| 21 |
+
def add_latents(self, latents: torch.FloatTensor):
|
| 22 |
+
self.history.append(latents)
|
| 23 |
+
|
| 24 |
+
def clear(self):
|
| 25 |
+
self.history = []
|
| 26 |
+
|
| 27 |
+
def dump_and_clear(self):
|
| 28 |
+
history = self.history
|
| 29 |
+
self.clear()
|
| 30 |
+
return history
|
models/diffusionModel/StableDiffusion.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
|
| 3 |
+
import torch
|
| 4 |
+
from diffusers import StableDiffusionPipeline
|
| 5 |
+
from BeamDiffusionModel.models.diffusionModel.configs.config_loader import CONFIG
|
| 6 |
+
from functools import partial
|
| 7 |
+
from BeamDiffusionModel.models.diffusionModel.Latents_Singleton import Latents
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class StableDiffusion:
|
| 11 |
+
def __init__(self):
|
| 12 |
+
self.device = "cuda" if CONFIG.get("stable_diffusion", {}).get("use_cuda", True) and torch.cuda.is_available() else "cpu"
|
| 13 |
+
self.torch_dtype = torch.float16 if CONFIG.get("stable_diffusion", {}).get("precision") == "float16" else torch.float32
|
| 14 |
+
|
| 15 |
+
print(f"Loading model: {CONFIG['stable_diffusion']['id']} on {self.device}")
|
| 16 |
+
|
| 17 |
+
self.pipe = StableDiffusionPipeline.from_pretrained(CONFIG["stable_diffusion"]["id"], torch_dtype=self.torch_dtype)
|
| 18 |
+
self.pipe.to(self.device)
|
| 19 |
+
|
| 20 |
+
self.unet = self.pipe.unet
|
| 21 |
+
self.vae = self.pipe.vae
|
| 22 |
+
|
| 23 |
+
print("Model loaded successfully!")
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def capture_latents(self, latents_store: Latents, pipe, step, timestep, callback_kwargs):
|
| 27 |
+
latents = callback_kwargs["latents"]
|
| 28 |
+
latents_store.add_latents(latents)
|
| 29 |
+
return callback_kwargs
|
| 30 |
+
|
| 31 |
+
def generate_image(self, prompt: str, latent=None, generator=None):
|
| 32 |
+
latents = Latents()
|
| 33 |
+
callback = partial(self.capture_latents, latents)
|
| 34 |
+
img = self.pipe(prompt, latents=latent, callback_on_step_end=callback,
|
| 35 |
+
generator=generator, callback_on_step_end_tensor_inputs=["latents"],
|
| 36 |
+
num_inference_steps=CONFIG["stable_diffusion"]["diffusion_settings"]["steps"]).images[0]
|
| 37 |
+
|
| 38 |
+
return img, latents.dump_and_clear()
|
models/diffusionModel/configs/config_loader.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import yaml
|
| 2 |
+
import os
|
| 3 |
+
import glob
|
| 4 |
+
|
| 5 |
+
CONFIG_DIR = "./BeamDiffusionModel/models/diffusionModel/configs" # Directory containing config files
|
| 6 |
+
|
| 7 |
+
def load_all_configs():
|
| 8 |
+
config = {} # Start with an empty config
|
| 9 |
+
|
| 10 |
+
# Find all YAML files in the directory (sorted for consistency)
|
| 11 |
+
config_files = sorted(glob.glob(os.path.join(CONFIG_DIR, "*.yml")))
|
| 12 |
+
|
| 13 |
+
for file_path in config_files:
|
| 14 |
+
with open(file_path, "r") as file:
|
| 15 |
+
new_config = yaml.safe_load(file) or {} # Load config (avoid None)
|
| 16 |
+
config = deep_merge(config, new_config) # Merge into main config
|
| 17 |
+
|
| 18 |
+
return config
|
| 19 |
+
|
| 20 |
+
def deep_merge(dict1, dict2):
|
| 21 |
+
"""Recursively merges two dictionaries (deep merge)."""
|
| 22 |
+
for key, value in dict2.items():
|
| 23 |
+
if isinstance(value, dict) and key in dict1 and isinstance(dict1[key], dict):
|
| 24 |
+
dict1[key] = deep_merge(dict1[key], value) # Recursively merge
|
| 25 |
+
else:
|
| 26 |
+
dict1[key] = value # Overwrite
|
| 27 |
+
return dict1
|
| 28 |
+
|
| 29 |
+
# Load and merge all configs automatically
|
| 30 |
+
CONFIG = load_all_configs()
|
| 31 |
+
|
| 32 |
+
print(os.getcwd())
|
| 33 |
+
print("Final Merged Config:")
|
| 34 |
+
print(CONFIG) # Display merged config
|
models/diffusionModel/configs/diffusionModel.yml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
stable_diffusion:
|
| 2 |
+
use_cuda: True
|
| 3 |
+
precision: float16
|
| 4 |
+
id: stabilityai/stable-diffusion-2-1
|
| 5 |
+
diffusion_settings:
|
| 6 |
+
steps: 50
|
tree/node.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from BeamDiffusionModel.models.clip.clip import clip
|
| 2 |
+
import numpy as np
|
| 3 |
+
|
| 4 |
+
class Node:
|
| 5 |
+
def __init__(self, step_text, image_path, latents, heat_map, step, generated_from_step, generated_from_latent, parent=None):
|
| 6 |
+
self.step_text = step_text
|
| 7 |
+
self.step = step
|
| 8 |
+
self.generated_from_step = generated_from_step
|
| 9 |
+
self.generated_from_latent = generated_from_latent
|
| 10 |
+
self.image = image_path
|
| 11 |
+
self.latents = latents
|
| 12 |
+
self.heat_map = heat_map
|
| 13 |
+
self.parent = parent
|
| 14 |
+
self.softmax = 0.
|
| 15 |
+
self.children = []
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def get_ancestors(self, n):
|
| 19 |
+
ancestors = [self]
|
| 20 |
+
current_node = self.parent
|
| 21 |
+
while current_node is not None and current_node.parent is not None and n > 0:
|
| 22 |
+
ancestors.append(current_node)
|
| 23 |
+
current_node = current_node.parent
|
| 24 |
+
n -= 1
|
| 25 |
+
return ancestors
|
| 26 |
+
|
| 27 |
+
def set_softmax(self, softmax, n_latents, n_max_latents, epsilon=1e-6):
|
| 28 |
+
self.softmax = np.log((softmax.cpu() * (1 / n_max_latents)) / (1 / n_latents) + epsilon)
|
| 29 |
+
|
| 30 |
+
def get_softmax(self):
|
| 31 |
+
return self.softmax
|
| 32 |
+
|
| 33 |
+
def add_child(self, node):
|
| 34 |
+
self.children.append(node)
|
| 35 |
+
|
| 36 |
+
def find_all_paths(self):
|
| 37 |
+
all_paths = []
|
| 38 |
+
stack = [(self, [self])] # Stack holds tuples of (current_node, path_to_current_node)
|
| 39 |
+
|
| 40 |
+
while stack:
|
| 41 |
+
current_node, path = stack.pop()
|
| 42 |
+
|
| 43 |
+
# If the current node is a leaf, add the path to all_paths
|
| 44 |
+
if not current_node.children:
|
| 45 |
+
all_paths.append(path)
|
| 46 |
+
else:
|
| 47 |
+
# Add all children to the stack with the updated path
|
| 48 |
+
for child in current_node.children:
|
| 49 |
+
stack.append((child, path + [child]))
|
| 50 |
+
|
| 51 |
+
return all_paths
|
| 52 |
+
|
| 53 |
+
def get_latent(self, idx):
|
| 54 |
+
return self.latents[idx]
|
| 55 |
+
|
| 56 |
+
def get_features(self):
|
| 57 |
+
text_embedding = clip.generate_embedding(self.step_text)
|
| 58 |
+
img_embedding = clip.generate_embedding(self.image)
|
| 59 |
+
return text_embedding, img_embedding
|
tree/tree.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from BeamDiffusionModel.tree.node import Node
|
| 2 |
+
import numpy as np
|
| 3 |
+
|
| 4 |
+
class BeamSearchTree:
|
| 5 |
+
def __init__(self, steps_back, beam_width, fixed_goals, n_steps):
|
| 6 |
+
self.root = Node(None, None, None,None, "Rand Seed", None, None)
|
| 7 |
+
self.nodes = [self.root]
|
| 8 |
+
self.n_steps = n_steps
|
| 9 |
+
self.steps_back = steps_back
|
| 10 |
+
self.fixed_goals = fixed_goals
|
| 11 |
+
self.beam_width = beam_width
|
| 12 |
+
|
| 13 |
+
def add_node(self, parent, step_text, step, generated_from_step, generated_from_latent, image, latents, heat_map):
|
| 14 |
+
new_node = Node(step_text, image, latents, heat_map, step, generated_from_step, generated_from_latent, parent)
|
| 15 |
+
parent.add_child(new_node)
|
| 16 |
+
self.nodes.append(new_node)
|
| 17 |
+
return new_node
|
| 18 |
+
|
| 19 |
+
def all_paths(self):
|
| 20 |
+
paths = []
|
| 21 |
+
# iterate over all the subtrees and get all the paths
|
| 22 |
+
for root in self.root.children:
|
| 23 |
+
paths.append(root.find_all_paths())
|
| 24 |
+
return paths
|
| 25 |
+
|
| 26 |
+
def get_previous_steps_features(self, node):
|
| 27 |
+
previous_steps = []
|
| 28 |
+
previous_images = []
|
| 29 |
+
current = node.parent
|
| 30 |
+
|
| 31 |
+
while current is not None and current.parent is not None:
|
| 32 |
+
text_embedding, img_embedding = current.get_features()
|
| 33 |
+
previous_steps = [text_embedding] + previous_steps
|
| 34 |
+
previous_images = [img_embedding] + previous_images
|
| 35 |
+
current = current.parent
|
| 36 |
+
return previous_steps, previous_images
|
| 37 |
+
|
| 38 |
+
def best_path(self):
|
| 39 |
+
all_paths = self.all_paths()
|
| 40 |
+
best_path = None
|
| 41 |
+
best_score = float('-inf')
|
| 42 |
+
for paths in all_paths:
|
| 43 |
+
for path in paths:
|
| 44 |
+
if len(path) < self.n_steps:
|
| 45 |
+
continue
|
| 46 |
+
score = 0.0
|
| 47 |
+
for node in path:
|
| 48 |
+
score += np.log(node.softmax) if node.softmax > 0 else node.softmax
|
| 49 |
+
|
| 50 |
+
if score > best_score:
|
| 51 |
+
best_score = score
|
| 52 |
+
best_path = path
|
| 53 |
+
return best_path, best_score
|
| 54 |
+
|
| 55 |
+
def best_path_imgs(self):
|
| 56 |
+
best_path, _ = self.best_path()
|
| 57 |
+
seq = []
|
| 58 |
+
for node in best_path:
|
| 59 |
+
seq.append(node.image)
|
| 60 |
+
return seq
|
| 61 |
+
|
| 62 |
+
def get_n_best_paths(self, n, path_length):
|
| 63 |
+
all_paths = self.all_paths()
|
| 64 |
+
best_paths = []
|
| 65 |
+
for paths in all_paths:
|
| 66 |
+
for path in paths:
|
| 67 |
+
if len(path) < path_length:
|
| 68 |
+
continue
|
| 69 |
+
score = float('-inf')
|
| 70 |
+
for node in path:
|
| 71 |
+
score += np.log(node.softmax) if node.softmax > 0 else node.softmax
|
| 72 |
+
if len(best_paths) < n:
|
| 73 |
+
best_paths.append((path, score))
|
| 74 |
+
else:
|
| 75 |
+
min_score = min(best_paths, key=lambda x: x[1])
|
| 76 |
+
if score > min_score[1]:
|
| 77 |
+
best_paths.remove(min_score)
|
| 78 |
+
best_paths.append((path, score))
|
| 79 |
+
|
| 80 |
+
new_best_paths = []
|
| 81 |
+
for (path, score) in best_paths:
|
| 82 |
+
new_best_paths.append(path)
|
| 83 |
+
|
| 84 |
+
return new_best_paths
|
utils/utils.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import PIL
|
| 2 |
+
from BeamDiffusionModel.models.diffusionModel.StableDiffusion import StableDiffusion
|
| 3 |
+
|
| 4 |
+
from BeamDiffusionModel.models.diffusionModel.configs.config_loader import CONFIG
|
| 5 |
+
from BeamDiffusionModel.models.clip.clip import Clip
|
| 6 |
+
import torch
|
| 7 |
+
import json
|
| 8 |
+
|
| 9 |
+
sd = StableDiffusion()
|
| 10 |
+
clip = Clip()
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def read_json(path):
|
| 14 |
+
with open(path, 'r') as f:
|
| 15 |
+
data = json.load(f)
|
| 16 |
+
return data
|
| 17 |
+
|
| 18 |
+
def get_img(path):
|
| 19 |
+
img = PIL.Image.open(path)
|
| 20 |
+
return img
|
| 21 |
+
|
| 22 |
+
def clip_score(step, imgs_path):
|
| 23 |
+
imgs = []
|
| 24 |
+
if isinstance(imgs_path, list):
|
| 25 |
+
for img_path in imgs_path:
|
| 26 |
+
img = get_img(img_path)
|
| 27 |
+
imgs.append(img)
|
| 28 |
+
else:
|
| 29 |
+
img = get_img(imgs_path)
|
| 30 |
+
imgs.append(img)
|
| 31 |
+
|
| 32 |
+
return clip.similarity(step, imgs)
|
| 33 |
+
|
| 34 |
+
def gen_img(caption, latent= None, seed=None):
|
| 35 |
+
system = "cuda" if CONFIG.get("diffusion_model", {}).get("use_cuda", True) and torch.cuda.is_available() else "cpu"
|
| 36 |
+
if seed:
|
| 37 |
+
generator = torch.Generator(system).manual_seed(seed)
|
| 38 |
+
else:
|
| 39 |
+
generator = None
|
| 40 |
+
img, latents = sd.generate_image(caption, generator=generator, latent=latent)
|
| 41 |
+
return latents, img
|
| 42 |
+
|