精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

從零開始,用英偉達T4、A10訓練小型文生視頻模型,幾小時搞定! 精華

發布于 2024-7-3 10:09
瀏覽
0收藏

OpenAI 的 Sora、Stability AI 的 Stable Video Diffusion 以及許多其他已經發布或未來將出現的文本生成視頻模型,是繼大語言模型 (LLM) 之后 2024 年最流行的 AI 趨勢之一。


在這篇博客中,作者將展示如何將從頭開始構建一個小規模的文本生成視頻模型,涵蓋了從理解理論概念、到編寫整個架構再到生成最終結果的所有內容。


由于作者沒有大算力的 GPU,所以僅編寫了小規模架構。以下是在不同處理器上訓練模型所需時間的比較。

從零開始,用英偉達T4、A10訓練小型文生視頻模型,幾小時搞定!-AI.x社區

作者表示,在 CPU 上運行顯然需要更長的時間來訓練模型。如果你需要快速測試代碼中的更改并查看結果,CPU 不是最佳選擇。因此建議使用 Colab 或 Kaggle 的 T4 GPU 進行更高效、更快速的訓練。


構建目標


我們采用了與傳統機器學習或深度學習模型類似的方法,即在數據集上進行訓練,然后在未見過數據上進行測試。在文本轉視頻的背景下,假設有一個包含 10 萬個狗撿球和貓追老鼠視頻的訓練數據集,然后訓練模型來生成貓撿球或狗追老鼠的視頻。


從零開始,用英偉達T4、A10訓練小型文生視頻模型,幾小時搞定!-AI.x社區

圖源:iStock, GettyImages


雖然此類訓練數據集在互聯網上很容易獲得,但所需的算力極高。因此,我們將使用由 Python 代碼生成的移動對象視頻數據集。同時使用 GAN(生成對抗網絡)架構來創建模型,而不是 OpenAI Sora 使用的擴散模型。


我們也嘗試使用擴散模型,但內存要求超出了自己的能力。另一方面,GAN 可以更容易、更快地進行訓練和測試。


準備條件


我們將使用 OOP(面向對象編程),因此必須對它以及神經網絡有基本的了解。此外 GAN(生成對抗網絡)的知識不是必需的,因為這里簡單介紹它們的架構。


  • OOP:https://www.youtube.com/watch?v=q2SGW2VgwAM
  • 神經網絡理論:https://www.youtube.com/watch?v=Jy4wM2X21u0
  • GAN 架構:https://www.youtube.com/watch?v=TpMIssRdhco
  • Python 基礎:https://www.youtube.com/watch?v=eWRfhZUzrAc?


了解 GAN 架構


什么是 GAN?


生成對抗網絡是一種深度學習模型,其中兩個神經網絡相互競爭:一個從給定的數據集創建新數據(如圖像或音樂),另一個則判斷數據是真實的還是虛假的。這個過程一直持續到生成的數據與原始數據無法區分。


真實世界應用


  • 生成圖像:GAN 根據文本 prompt 創建逼真的圖像或修改現有圖像,例如增強分辨率或為黑白照片添加顏色。
  • 數據增強:GAN 生成合成數據來訓練其他機器學習模型,例如為欺詐檢測系統創建欺詐交易數據。
  • 補充缺失信息:GAN 可以填充缺失數據,例如根據地形圖生成地下圖像以用于能源應用。
  • 生成 3D 模型:GAN 將 2D 圖像轉換為 3D 模型,在醫療保健等領域非常有用,可用于為手術規劃創建逼真的器官圖像。


GAN 工作原理


GAN 由兩個深度神經網絡組成:生成器和判別器。這兩個網絡在對抗設置中一起訓練,其中一個網絡生成新數據,另一個網絡評估數據是真是假。


從零開始,用英偉達T4、A10訓練小型文生視頻模型,幾小時搞定!-AI.x社區


GAN 訓練示例


讓我們以圖像到圖像的轉換為例,解釋一下 GAN 模型,重點是修改人臉。


1. 輸入圖像:輸入圖像是一張真實的人臉圖像。

2. 屬性修改:生成器會修改人臉的屬性,比如給眼睛加上墨鏡。

3. 生成圖像:生成器會創建一組添加了太陽鏡的圖像。

4. 判別器的任務:判別器接收到混合的真實圖像(帶有太陽鏡的人)和生成的圖像(添加了太陽鏡的人臉)。 

5. 評估:判別器嘗試區分真實圖像和生成圖像。 

6. 反饋回路:如果判別器正確識別出假圖像,生成器會調整其參數以生成更逼真的圖像。如果生成器成功欺騙了判別器,判別器會更新其參數以提高檢測能力。 


通過這一對抗過程,兩個網絡都在不斷改進。生成器越來越善于生成逼真的圖像,而判別器則越來越善于識別假圖像,直到達到平衡,判別器再也無法區分真實圖像和生成的圖像。此時,GAN 已成功學會生成逼真的修改圖像。


設置背景


我們將使用一系列 Python 庫,讓我們導入它們。


# Operating System module for interacting with the operating system
import os


# Module for generating random numbers
import random


# Module for numerical operations
import numpy as np


# OpenCV library for image processing
import cv2


# Python Imaging Library for image processing
from PIL import Image, ImageDraw, ImageFont


# PyTorch library for deep learning
import torch


# Dataset class for creating custom datasets in PyTorch
from torch.utils.data import Dataset


# Module for image transformations
import torchvision.transforms as transforms


# Neural network module in PyTorch
import torch.nn as nn


# Optimization algorithms in PyTorch
import torch.optim as optim


# Function for padding sequences in PyTorch
from torch.nn.utils.rnn import pad_sequence


# Function for saving images in PyTorch
from torchvision.utils import save_image


# Module for plotting graphs and images
import matplotlib.pyplot as plt


# Module for displaying rich content in IPython environments
from IPython.display import clear_output, display, HTML


# Module for encoding and decoding binary data to text
import base64


現在我們已經導入了所有的庫,下一步就是定義我們的訓練數據,用于訓練 GAN 架構。


對訓練數據進行編碼


我們需要至少 10000 個視頻作為訓練數據。為什么呢?因為我測試了較小數量的視頻,結果非常糟糕,幾乎沒有任何效果。下一個重要問題是:這些視頻內容是什么?  我們的訓練視頻數據集包括一個圓圈以不同方向和不同運動方式移動的視頻。讓我們來編寫代碼并生成 10,000 個視頻,看看它的效果如何。 


# Create a directory named 'training_dataset'
os.makedirs('training_dataset', exist_ok=True)


# Define the number of videos to generate for the dataset
num_videos = 10000


# Define the number of frames per video (1 Second Video)
frames_per_video = 10


# Define the size of each image in the dataset
img_size = (64, 64)


# Define the size of the shapes (Circle)
shape_size = 10


設置一些基本參數后,接下來我們需要定義訓練數據集的文本 prompt,并據此生成訓練視頻。


# Define text prompts and corresponding movements for circles
prompts_and_movements = [
 ("circle moving down", "circle", "down"), # Move circle downward
 ("circle moving left", "circle", "left"), # Move circle leftward
 ("circle moving right", "circle", "right"), # Move circle rightward
 ("circle moving diagonally up-right", "circle", "diagonal_up_right"), # Move circle diagonally up-right
 ("circle moving diagonally down-left", "circle", "diagonal_down_left"), # Move circle diagonally down-left
 ("circle moving diagonally up-left", "circle", "diagonal_up_left"), # Move circle diagonally up-left
 ("circle moving diagonally down-right", "circle", "diagonal_down_right"), # Move circle diagonally down-right
 ("circle rotating clockwise", "circle", "rotate_clockwise"), # Rotate circle clockwise
 ("circle rotating counter-clockwise", "circle", "rotate_counter_clockwise"), # Rotate circle counter-clockwise
 ("circle shrinking", "circle", "shrink"), # Shrink circle
 ("circle expanding", "circle", "expand"), # Expand circle
 ("circle bouncing vertically", "circle", "bounce_vertical"), # Bounce circle vertically
 ("circle bouncing horizontally", "circle", "bounce_horizontal"), # Bounce circle horizontally
 ("circle zigzagging vertically", "circle", "zigzag_vertical"), # Zigzag circle vertically
 ("circle zigzagging horizontally", "circle", "zigzag_horizontal"), # Zigzag circle horizontally
 ("circle moving up-left", "circle", "up_left"), # Move circle up-left
 ("circle moving down-right", "circle", "down_right"), # Move circle down-right
 ("circle moving down-left", "circle", "down_left"), # Move circle down-left
]


我們已經利用這些 prompt 定義了圓的幾個運動軌跡。現在,我們需要編寫一些數學公式,以便根據 prompt 移動圓。


# Define function with parameters
def create_image_with_moving_shape(size, frame_num, shape, direction):
 
 # Create a new RGB image with specified size and white background
 img = Image.new('RGB', size, color=(255, 255, 255)) 


 # Create a drawing context for the image
 draw = ImageDraw.Draw(img) 


 # Calculate the center coordinates of the image
 center_x, center_y = size[0] // 2, size[1] // 2 


 # Initialize position with center for all movements
 position = (center_x, center_y) 


 # Define a dictionary mapping directions to their respective position adjustments or image transformations
 direction_map = { 
 # Adjust position downwards based on frame number
 "down": (0, frame_num * 5 % size[1]), 
 # Adjust position to the left based on frame number
 "left": (-frame_num * 5 % size[0], 0), 
 # Adjust position to the right based on frame number
 "right": (frame_num * 5 % size[0], 0), 
 # Adjust position diagonally up and to the right
 "diagonal_up_right": (frame_num * 5 % size[0], -frame_num * 5 % size[1]), 
 # Adjust position diagonally down and to the left
 "diagonal_down_left": (-frame_num * 5 % size[0], frame_num * 5 % size[1]), 
 # Adjust position diagonally up and to the left
 "diagonal_up_left": (-frame_num * 5 % size[0], -frame_num * 5 % size[1]), 
 # Adjust position diagonally down and to the right
 "diagonal_down_right": (frame_num * 5 % size[0], frame_num * 5 % size[1]), 
 # Rotate the image clockwise based on frame number
 "rotate_clockwise": img.rotate(frame_num * 10 % 360, center=(center_x, center_y), fillcolor=(255, 255, 255)), 
 # Rotate the image counter-clockwise based on frame number
 "rotate_counter_clockwise": img.rotate(-frame_num * 10 % 360, center=(center_x, center_y), fillcolor=(255, 255, 255)), 
 # Adjust position for a bouncing effect vertically
 "bounce_vertical": (0, center_y - abs(frame_num * 5 % size[1] - center_y)), 
 # Adjust position for a bouncing effect horizontally
 "bounce_horizontal": (center_x - abs(frame_num * 5 % size[0] - center_x), 0), 
 # Adjust position for a zigzag effect vertically
 "zigzag_vertical": (0, center_y - frame_num * 5 % size[1]) if frame_num % 2 == 0 else (0, center_y + frame_num * 5 % size[1]), 
 # Adjust position for a zigzag effect horizontally
 "zigzag_horizontal": (center_x - frame_num * 5 % size[0], center_y) if frame_num % 2 == 0 else (center_x + frame_num * 5 % size[0], center_y), 
 # Adjust position upwards and to the right based on frame number
 "up_right": (frame_num * 5 % size[0], -frame_num * 5 % size[1]), 
 # Adjust position upwards and to the left based on frame number
 "up_left": (-frame_num * 5 % size[0], -frame_num * 5 % size[1]), 
 # Adjust position downwards and to the right based on frame number
 "down_right": (frame_num * 5 % size[0], frame_num * 5 % size[1]), 
 # Adjust position downwards and to the left based on frame number
 "down_left": (-frame_num * 5 % size[0], frame_num * 5 % size[1]) 
 }


 # Check if direction is in the direction map
 if direction in direction_map: 
 # Check if the direction maps to a position adjustment
 if isinstance(direction_map[direction], tuple): 
 # Update position based on the adjustment
 position = tuple(np.add(position, direction_map[direction])) 
 else: # If the direction maps to an image transformation
 # Update the image based on the transformation
 img = direction_map[direction] 


 # Return the image as a numpy array
 return np.array(img)


上述函數用于根據所選方向在每一幀中移動我們的圓。我們只需在其上運行一個循環,直至生成所有視頻的次數。


# Iterate over the number of videos to generate
for i in range(num_videos):
    # Randomly choose a prompt and movement from the predefined list
    prompt, shape, direction = random.choice(prompts_and_movements)
    
    # Create a directory for the current video
    video_dir = f'training_dataset/video_{i}'
    os.makedirs(video_dir, exist_ok=True)
    
    # Write the chosen prompt to a text file in the video directory
    with open(f'{video_dir}/prompt.txt', 'w') as f:
        f.write(prompt)
    
    # Generate frames for the current video
    for frame_num in range(frames_per_video):
        # Create an image with a moving shape based on the current frame number, shape, and direction
        img = create_image_with_moving_shape(img_size, frame_num, shape, direction)
        
        # Save the generated image as a PNG file in the video directory
        cv2.imwrite(f'{video_dir}/frame_{frame_num}.png', img)


運行上述代碼后,就會生成整個訓練數據集。以下是訓練數據集文件的結構。


從零開始,用英偉達T4、A10訓練小型文生視頻模型,幾小時搞定!-AI.x社區


每個訓練視頻文件夾包含其幀以及對應的文本 prompt。讓我們看一下我們的訓練數據集樣本。


在我們的訓練數據集中,我們沒有包含圓圈先向上移動然后向右移動的運動。我們將使用這個作為測試 prompt,來評估我們訓練的模型在未見過的數據上的表現。


從零開始,用英偉達T4、A10訓練小型文生視頻模型,幾小時搞定!-AI.x社區


還有一個重要的要點需要注意,我們的訓練數據包含許多物體從場景中移出或部分出現在攝像機前方的樣本,類似于我們在 OpenAI Sora 演示視頻中觀察到的情況。 


從零開始,用英偉達T4、A10訓練小型文生視頻模型,幾小時搞定!-AI.x社區


在我們的訓練數據中包含此類樣本的原因是為了測試當圓圈從角落進入場景時,模型是否能夠保持一致性而不會破壞其形狀。


現在我們的訓練數據已經生成,需要將訓練視頻轉換為張量,這是 PyTorch 等深度學習框架中使用的主要數據類型。此外,通過將數據縮放到較小的范圍,執行歸一化等轉換有助于提高訓練架構的收斂性和穩定性。


預處理訓練數據


我們必須為文本轉視頻任務編寫一個數據集類,它可以從訓練數據集目錄中讀取視頻幀及其相應的文本 prompt,使其可以在 PyTorch 中使用。


# Define a dataset class inheriting from torch.utils.data.Dataset
class TextToVideoDataset(Dataset):
    def __init__(self, root_dir, transform=None):
        # Initialize the dataset with root directory and optional transform
        self.root_dir = root_dir
        self.transform = transform
        # List all subdirectories in the root directory
        self.video_dirs = [os.path.join(root_dir, d) for d in os.listdir(root_dir) if os.path.isdir(os.path.join(root_dir, d))]
        # Initialize lists to store frame paths and corresponding prompts
        self.frame_paths = []
        self.prompts = []


        # Loop through each video directory
        for video_dir in self.video_dirs:
            # List all PNG files in the video directory and store their paths
            frames = [os.path.join(video_dir, f) for f in os.listdir(video_dir) if f.endswith('.png')]
            self.frame_paths.extend(frames)
            # Read the prompt text file in the video directory and store its content
            with open(os.path.join(video_dir, 'prompt.txt'), 'r') as f:
                prompt = f.read().strip()
            # Repeat the prompt for each frame in the video and store in prompts list
            self.prompts.extend([prompt] * len(frames))


    # Return the total number of samples in the dataset
    def __len__(self):
        return len(self.frame_paths)


    # Retrieve a sample from the dataset given an index
    def __getitem__(self, idx):
        # Get the path of the frame corresponding to the given index
        frame_path = self.frame_paths[idx]
        # Open the image using PIL (Python Imaging Library)
        image = Image.open(frame_path)
        # Get the prompt corresponding to the given index
        prompt = self.prompts[idx]


        # Apply transformation if specified
        if self.transform:
            image = self.transform(image)


        # Return the transformed image and the prompt
        return image, prompt


在繼續編寫架構代碼之前,我們需要對訓練數據進行歸一化處理。我們使用 16 的 batch 大小并對數據進行混洗以引入更多隨機性。


實現文本嵌入層


你可能已經看到,在 Transformer 架構中,起點是將文本輸入轉換為嵌入,從而在多頭注意力中進行進一步處理。類似地,我們在這里必須編寫一個文本嵌入層。基于該層,GAN 架構訓練在我們的嵌入數據和圖像張量上進行。


# Define a class for text embedding
class TextEmbedding(nn.Module):
    # Constructor method with vocab_size and embed_size parameters
    def __init__(self, vocab_size, embed_size):
        # Call the superclass constructor
        super(TextEmbedding, self).__init__()
        # Initialize embedding layer
        self.embedding = nn.Embedding(vocab_size, embed_size)


    # Define the forward pass method
    def forward(self, x):
        # Return embedded representation of input
        return self.embedding(x)


詞匯量將基于我們的訓練數據,在稍后進行計算。嵌入大小將為 10。如果使用更大的數據集,你還可以使用 Hugging Face 上已有的嵌入模型。


實現生成器層


現在我們已經知道生成器在 GAN 中的作用,接下來讓我們對這一層進行編碼,然后了解其內容。


class Generator(nn.Module):
 def __init__(self, text_embed_size):
 super(Generator, self).__init__()
 
 # Fully connected layer that takes noise and text embedding as input
 self.fc1 = nn.Linear(100 + text_embed_size, 256 * 8 * 8)
 
 # Transposed convolutional layers to upsample the input
 self.deconv1 = nn.ConvTranspose2d(256, 128, 4, 2, 1)
 self.deconv2 = nn.ConvTranspose2d(128, 64, 4, 2, 1)
 self.deconv3 = nn.ConvTranspose2d(64, 3, 4, 2, 1) # Output has 3 channels for RGB images
 
 # Activation functions
 self.relu = nn.ReLU(True) # ReLU activation function
 self.tanh = nn.Tanh() # Tanh activation function for final output


 def forward(self, noise, text_embed):
 # Concatenate noise and text embedding along the channel dimension
 x = torch.cat((noise, text_embed), dim=1)
 
 # Fully connected layer followed by reshaping to 4D tensor
 x = self.fc1(x).view(-1, 256, 8, 8)
 
 # Upsampling through transposed convolution layers with ReLU activation
 x = self.relu(self.deconv1(x))
 x = self.relu(self.deconv2(x))
 
 # Final layer with Tanh activation to ensure output values are between -1 and 1 (for images)
 x = self.tanh(self.deconv3(x))
 
 return x


該 Generator 類負責根據隨機噪聲和文本嵌入的組合創建視頻幀,旨在根據給定的文本描述生成逼真的視頻幀。該網絡從完全連接層 (nn.Linear) 開始,將噪聲向量和文本嵌入組合成單個特征向量。然后,該向量被重新整形并經過一系列的轉置卷積層 (nn.ConvTranspose2d),這些層將特征圖逐步上采樣到所需的視頻幀大小。


這些層使用 ReLU 激活 (nn.ReLU) 實現非線性,最后一層使用 Tanh 激活 (nn.Tanh) 將輸出縮放到 [-1, 1] 的范圍。因此,生成器將抽象的高維輸入轉換為以視覺方式表示輸入文本的連貫視頻幀。


實現判別器層


在編寫完生成器層之后,我們需要實現另一半,即判別器部分。


class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        
        # Convolutional layers to process input images
        self.conv1 = nn.Conv2d(3, 64, 4, 2, 1)   # 3 input channels (RGB), 64 output channels, kernel size 4x4, stride 2, padding 1
        self.conv2 = nn.Conv2d(64, 128, 4, 2, 1) # 64 input channels, 128 output channels, kernel size 4x4, stride 2, padding 1
        self.conv3 = nn.Conv2d(128, 256, 4, 2, 1) # 128 input channels, 256 output channels, kernel size 4x4, stride 2, padding 1
        
        # Fully connected layer for classification
        self.fc1 = nn.Linear(256 * 8 * 8, 1)  # Input size 256x8x8 (output size of last convolution), output size 1 (binary classification)
        
        # Activation functions
        self.leaky_relu = nn.LeakyReLU(0.2, inplace=True)  # Leaky ReLU activation with negative slope 0.2
        self.sigmoid = nn.Sigmoid()  # Sigmoid activation for final output (probability)


    def forward(self, input):
        # Pass input through convolutional layers with LeakyReLU activation
        x = self.leaky_relu(self.conv1(input))
        x = self.leaky_relu(self.conv2(x))
        x = self.leaky_relu(self.conv3(x))
        
        # Flatten the output of convolutional layers
        x = x.view(-1, 256 * 8 * 8)
        
        # Pass through fully connected layer with Sigmoid activation for binary classification
        x = self.sigmoid(self.fc1(x))
        
        return x


判別器類用作二元分類器,區分真實視頻幀和生成的視頻幀。目的是評估視頻幀的真實性,從而指導生成器產生更真實的輸出。該網絡由卷積層 (nn.Conv2d) 組成,這些卷積層從輸入視頻幀中提取分層特征, Leaky ReLU 激活 (nn.LeakyReLU) 增加非線性,同時允許負值的小梯度。


然后,特征圖被展平并通過完全連接層 (nn.Linear),最終以 S 形激活 (nn.Sigmoid) 輸出指示幀是真實還是假的概率分數。


通過訓練判別器準確地對幀進行分類,生成器同時接受訓練以創建更令人信服的視頻幀,從而騙過判別器。


編寫訓練參數


我們必須設置用于訓練 GAN 的基礎組件,例如損失函數、優化器等。


# Check for GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")


# Create a simple vocabulary for text prompts
all_prompts = [prompt for prompt, _, _ in prompts_and_movements]  # Extract all prompts from prompts_and_movements list
vocab = {word: idx for idx, word in enumerate(set(" ".join(all_prompts).split()))}  # Create a vocabulary dictionary where each unique word is assigned an index
vocab_size = len(vocab)  # Size of the vocabulary
embed_size = 10  # Size of the text embedding vector


def encode_text(prompt):
    # Encode a given prompt into a tensor of indices using the vocabulary
    return torch.tensor([vocab[word] for word in prompt.split()])


# Initialize models, loss function, and optimizers
text_embedding = TextEmbedding(vocab_size, embed_size).to(device)  # Initialize TextEmbedding model with vocab_size and embed_size
netG = Generator(embed_size).to(device)  # Initialize Generator model with embed_size
netD = Discriminator().to(device)  # Initialize Discriminator model
criterion = nn.BCELoss().to(device)  # Binary Cross Entropy loss function
optimizerD = optim.Adam(netD.parameters(), lr=0.0002, betas=(0.5, 0.999))  # Adam optimizer for Discriminator
optimizerG = optim.Adam(netG.parameters(), lr=0.0002, betas=(0.5, 0.999))  # Adam optimizer for Generator


這是我們必須轉換代碼以在 GPU 上運行的部分(如果可用)。我們已經編寫了代碼來查找 vocab_size,并且我們正在為生成器和判別器使用 ADAM 優化器。你可以選擇自己的優化器。在這里,我們將學習率設置為較小的值 0.0002,嵌入大小為 10,這比其他可供公眾使用的 Hugging Face 模型要小得多。


編寫訓練 loop


就像其他神經網絡一樣,我們將以類似的方式對 GAN 架構訓練進行編碼。


# Number of epochs
num_epochs = 13


# Iterate over each epoch
for epoch in range(num_epochs):
    # Iterate over each batch of data
    for i, (data, prompts) in enumerate(dataloader):
        # Move real data to device
        real_data = data.to(device)
        
        # Convert prompts to list
        prompts = [prompt for prompt in prompts]


        # Update Discriminator
        netD.zero_grad()  # Zero the gradients of the Discriminator
        batch_size = real_data.size(0)  # Get the batch size
        labels = torch.ones(batch_size, 1).to(device)  # Create labels for real data (ones)
        output = netD(real_data)  # Forward pass real data through Discriminator
        lossD_real = criterion(output, labels)  # Calculate loss on real data
        lossD_real.backward()  # Backward pass to calculate gradients
       
        # Generate fake data
        noise = torch.randn(batch_size, 100).to(device)  # Generate random noise
        text_embeds = torch.stack([text_embedding(encode_text(prompt).to(device)).mean(dim=0) for prompt in prompts])  # Encode prompts into text embeddings
        fake_data = netG(noise, text_embeds)  # Generate fake data from noise and text embeddings
        labels = torch.zeros(batch_size, 1).to(device)  # Create labels for fake data (zeros)
        output = netD(fake_data.detach())  # Forward pass fake data through Discriminator (detach to avoid gradients flowing back to Generator)
        lossD_fake = criterion(output, labels)  # Calculate loss on fake data
        lossD_fake.backward()  # Backward pass to calculate gradients
        optimizerD.step()  # Update Discriminator parameters


        # Update Generator
        netG.zero_grad()  # Zero the gradients of the Generator
        labels = torch.ones(batch_size, 1).to(device)  # Create labels for fake data (ones) to fool Discriminator
        output = netD(fake_data)  # Forward pass fake data (now updated) through Discriminator
        lossG = criterion(output, labels)  # Calculate loss for Generator based on Discriminator's response
        lossG.backward()  # Backward pass to calculate gradients
        optimizerG.step()  # Update Generator parameters
    
    # Print epoch information
    print(f"Epoch [{epoch + 1}/{num_epochs}] Loss D: {lossD_real + lossD_fake}, Loss G: {lossG}")


通過反向傳播,我們的損失將針對生成器和判別器進行調整。我們在訓練 loop 中使用了 13 個 epoch。我們測試了不同的值,但如果 epoch 高于這個值,結果并沒有太大差異。此外,過度擬合的風險很高。如果我們的數據集更加多樣化,包含更多動作和形狀,則可以考慮使用更高的 epoch,但在這里沒有這樣做。


當我們運行此代碼時,它會開始訓練,并在每個 epoch 之后 print 生成器和判別器的損失。


## OUTPUT ##

Epoch [1/13] Loss D: 0.8798642754554749, Loss G: 1.300612449645996
Epoch [2/13] Loss D: 0.8235711455345154, Loss G: 1.3729925155639648
Epoch [3/13] Loss D: 0.6098687052726746, Loss G: 1.3266581296920776

...


保存訓練的模型


訓練完成后,我們需要保存訓練好的 GAN 架構的判別器和生成器,這只需兩行代碼即可實現。


# Save the Generator model's state dictionary to a file named 'generator.pth'
torch.save(netG.state_dict(), 'generator.pth')

# Save the Discriminator model's state dictionary to a file named 'discriminator.pth'
torch.save(netD.state_dict(), 'discriminator.pth')


生成 AI 視頻


正如我們所討論的,我們在未見過的數據上測試模型的方法與我們訓練數據中涉及狗取球和貓追老鼠的示例類似。因此,我們的測試 prompt 可能涉及貓取球或狗追老鼠等場景。


在我們的特定情況下,圓圈向上移動然后向右移動的運動在訓練數據中不存在,因此模型不熟悉這種特定運動。但是,模型已經在其他動作上進行了訓練。我們可以使用此動作作為 prompt 來測試我們訓練過的模型并觀察其性能。


# Inference function to generate a video based on a given text promptdef generate_video(text_prompt, num_frames=10):    # Create a directory for the generated video frames based on the text prompt    os.makedirs(f'generated_video_{text_prompt.replace(" ", "_")}', exist_ok=True)        # Encode the text prompt into a text embedding tensor    text_embed = text_embedding(encode_text(text_prompt).to(device)).mean(dim=0).unsqueeze(0)        # Generate frames for the video    for frame_num in range(num_frames):        # Generate random noise        noise = torch.randn(1, 100).to(device)                # Generate a fake frame using the Generator network        with torch.no_grad():            fake_frame = netG(noise, text_embed)                # Save the generated fake frame as an image file        save_image(fake_frame, f'generated_video_{text_prompt.replace(" ", "_")}/frame_{frame_num}.png')# usage of the generate_video function with a specific text promptgenerate_video('circle moving up-right')


當我們運行上述代碼時,它將生成一個目錄,其中包含我們生成視頻的所有幀。我們需要使用一些代碼將所有這些幀合并為一個短視頻。


# Define the path to your folder containing the PNG frames
folder_path = 'generated_video_circle_moving_up-right'

# Get the list of all PNG files in the folder
image_files = [f for f in os.listdir(folder_path) if f.endswith('.png')]

# Sort the images by name (assuming they are numbered sequentially)
image_files.sort()

# Create a list to store the frames
frames = []

# Read each image and append it to the frames list
for image_file in image_files:
 image_path = os.path.join(folder_path, image_file)
 frame = cv2.imread(image_path)
 frames.append(frame)

# Convert the frames list to a numpy array for easier processing
frames = np.array(frames)

# Define the frame rate (frames per second)
fps = 10

# Create a video writer object
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('generated_video.avi', fourcc, fps, (frames[0].shape[1], frames[0].shape[0]))

# Write each frame to the video
for frame in frames:
 out.write(frame)

# Release the video writer
out.release()


確保文件夾路徑指向你新生成的視頻所在的位置。運行此代碼后,你將成功創建 AI 視頻。讓我們看看它是什么樣子。


從零開始,用英偉達T4、A10訓練小型文生視頻模型,幾小時搞定!-AI.x社區


我們進行了多次訓練,訓練次數相同。在兩種情況下,圓圈都是從底部開始,出現一半。好消息是,我們的模型在兩種情況下都嘗試執行直立運動。


例如,在嘗試 1 中,圓圈沿對角線向上移動,然后執行向上運動,而在嘗試 2 中,圓圈沿對角線移動,同時尺寸縮小。在兩種情況下,圓圈都沒有向左移動或完全消失,這是一個好兆頭。


最后,作者表示已經測試了該架構的各個方面,發現訓練數據是關鍵。通過在數據集中包含更多動作和形狀,你可以增加可變性并提高模型的性能。由于數據是通過代碼生成的,因此生成更多樣的數據不會花費太多時間;相反,你可以專注于完善邏輯。


此外,文章中討論的 GAN 架構相對簡單。你可以通過集成高級技術或使用語言模型嵌入 (LLM) 而不是基本神經網絡嵌入來使其更復雜。此外,調整嵌入大小等參數會顯著影響模型的有效性。


本文轉自 AI生成未來 ,作者:Fareed Khan


原文鏈接:??https://mp.weixin.qq.com/s/wd1_rg-ckhfNreatjjOKag??

收藏
回復
舉報
回復
相關推薦
久久99国产精一区二区三区| 黑人精品视频| 久久黄色级2电影| 久久综合免费视频| 亚洲啪av永久无码精品放毛片 | 2022国产精品视频| 国产脚交av在线一区二区| 国产高清视频免费在线观看| 理论片一区二区在线| 欧美视频在线观看一区| 女人帮男人橹视频播放| 岛国最新视频免费在线观看| 国产精品1区2区3区在线观看| 欧美一级淫片aaaaaaa视频| 永久免费观看片现看| 超碰成人免费| 欧美另类z0zxhd电影| 国产极品尤物在线| 精精国产xxxx视频在线| 久久久久久免费网| a级国产乱理论片在线观看99| 二区视频在线观看| 欧美有码视频| 在线视频亚洲欧美| 免费看黄色aaaaaa 片| 精品中文视频| 欧美三区在线观看| 国产亚洲综合视频| 国产美女一区视频| 亚洲天堂av一区| 日韩欧美一区二区三区四区五区| 欧美一区二区公司| 国产精品18久久久久久久久久久久| 国产va免费精品高清在线| 久久免费黄色网址| 中文字幕日韩一区二区不卡 | 在线xxxx| 一区免费观看视频| 亚欧精品在线| 美女做暖暖视频免费在线观看全部网址91| 国产成人欧美日韩在线电影| 国产中文字幕91| 天堂av免费在线观看| 香蕉久久国产| 68精品久久久久久欧美| 国产亚洲精品码| 欧美三级在线| 欧美日本中文字幕| 麻豆视频在线免费看| 97精品在线| 色噜噜狠狠色综合网图区| 成人免费无遮挡无码黄漫视频| 精品久久ai电影| 精品va天堂亚洲国产| 香蕉在线观看视频| **爰片久久毛片| 欧美不卡视频一区| 黑人巨大猛交丰满少妇| 日韩精品视频中文字幕| 日韩三区在线观看| 少妇高潮一69aⅹ| 亚洲日本va中文字幕| 精品少妇一区二区三区| 蜜臀aⅴ国产精品久久久国产老师| av在线成人| 日韩三级av在线播放| 韩国三级在线播放| 精品女人视频| 亚洲精品视频网上网址在线观看| 三级网站在线免费观看| 精品一区二区三| 日韩中文字幕在线免费观看| 国产精品免费在线视频| 欧美激情国产在线| 欧美成人激情视频免费观看| 久久久久久久久精| 一本综合久久| 国产精品九九九| 97久久人国产精品婷婷| 国产精品一区二区x88av| 成人欧美一区二区三区视频xxx| 欧美一级在线免费观看| 国产情人综合久久777777| 无码免费一区二区三区免费播放 | 亚洲精品视频在线观看免费| 欧美久久久久久久久久久久久久| 678在线观看视频| 色婷婷久久久久swag精品| 黄色成人免费看| 高清国产一区二区三区四区五区| 欧美成人r级一区二区三区| 亚洲精品乱码久久久久久久| 欧美裸体在线版观看完整版| 欧美成在线视频| 亚洲日本韩国在线| 久久成人免费电影| 精品国产一区二区三区麻豆小说| 99青草视频在线播放视| 亚洲一区二区三区影院| 亚洲黄色a v| 91国内精品| 中文字幕av一区中文字幕天堂| 强行糟蹋人妻hd中文| 99国产精品视频免费观看一公开| 国产精品一区二区久久久久| 国产综合视频在线| 综合激情成人伊人| avav在线看| 欧美一区一区| 中文字幕亚洲精品| 国产午夜精品一区二区理论影院| 免费在线观看不卡| 久久99精品久久久久久秒播放器 | 亚洲综合丝袜美腿| 999在线免费视频| 国产成人一二片| www.久久色.com| 亚洲欧美偷拍视频| 成人性色生活片免费看爆迷你毛片| 婷婷亚洲婷婷综合色香五月| 美女高潮在线观看| 日韩精品最新网址| 成人一级片免费看| 丝袜诱惑制服诱惑色一区在线观看 | 日韩高清人体午夜| 欧美成人三级视频| 精品制服美女丁香| 亚洲看片网站| 日韩pacopacomama| 日韩久久精品电影| 天堂资源在线播放| 国产精品一区二区久久不卡| 中文字幕精品—区二区日日骚| 成人亚洲欧美| 亚洲跨种族黑人xxx| 在线看成人av| 国产91在线观看丝袜| 无颜之月在线看| 爱情电影网av一区二区| 在线观看国产欧美| 香蕉污视频在线观看| 91久色porny| 女性女同性aⅴ免费观女性恋 | 日韩欧美专区在线| 成人高潮免费视频| 国产综合色在线视频区| 伊人情人网综合| 青青国产精品| 最近2019中文字幕在线高清| 在线观看毛片av| 国产精品久久久久毛片软件| 亚洲免费黄色网| 久久福利影院| 91久久久久久久久久久久久| 日本高清在线观看wwwww色| 欧美日韩在线播| 国产又黄又粗又猛又爽的| 日韩高清一区二区| 先锋影音网一区| 国产精品亚洲成在人线| xxxxx91麻豆| 国产精品高潮呻吟av| 亚洲精品视频在线观看网站| 最新国产精品自拍| 国产精品久久久久久模特| 欧美久久久久久| 91在线成人| 日韩在线观看免费全| 国产富婆一级全黄大片| 夜夜爽夜夜爽精品视频| 黄色网址在线视频| 久久一二三区| 中文字幕中文字幕在线中一区高清| 亚洲高清影院| 久久久久久久一| 日本免费不卡| 欧美日产国产精品| 黄色一级免费视频| 2欧美一区二区三区在线观看视频 337p粉嫩大胆噜噜噜噜噜91av | 在线日本视频| 欧美成人vps| 久久久久在线视频| 最新不卡av在线| 少妇户外露出[11p]| 日本亚洲三级在线| 成人污网站在线观看| 亚洲第一论坛sis| 国产精品丝袜高跟| 黄网av在线| 原创国产精品91| www.激情五月| 色悠悠久久综合| 老女人性淫交视频| 26uuu亚洲综合色| 日本一二三四区视频| 午夜在线观看免费一区| 亚洲视频电影| 欧美sss在线视频| 91久久国产婷婷一区二区| av在线视屏| 久久天天躁狠狠躁夜夜躁2014| 日韩一级片免费观看| 欧美日韩在线播放三区| 日韩美女黄色片| 综合色中文字幕| 国产人妻一区二区| 国产不卡视频一区| 色婷婷综合网站| 一本久道综合久久精品| 伊人久久大香线蕉精品| 亚洲深夜福利在线观看| 超碰97在线资源| 成人亚洲免费| 秋霞av国产精品一区| 久久久123| yw.139尤物在线精品视频| 日韩毛片在线一区二区毛片| 欧美成人精品3d动漫h| 夜夜爽8888| 91久久精品网| 综合激情网五月| 亚洲综合偷拍欧美一区色| fc2ppv在线播放| 国产欧美一区二区精品性| 亚洲最大免费视频| 成人性生交大片免费| 在线观看中文av| 麻豆精品国产传媒mv男同| 99999精品视频| 亚洲天堂成人| 大胆欧美熟妇xx| 一区二区三区午夜探花| 亚洲一二区在线| 欧美一站二站| 日韩av电影免费在线观看| 亚洲精品合集| 久久综合一区二区三区| 国产精品99久久免费观看| 成人免费视频网站入口| 美女精品视频在线| 亚洲在线视频福利| 成人影院网站ww555久久精品| 国产美女精彩久久| yiren22亚洲综合| 国产精品爽爽爽爽爽爽在线观看| 日本一区二区三区视频在线| 国产精品av免费在线观看| 日本精品另类| 国产精品日韩在线| 亚洲精品66| 91九色蝌蚪国产| 久久亚洲精精品中文字幕| 99re在线国产| 国产精品玖玖玖在线资源| 国产在线播放一区二区| 日韩精品免费一区二区夜夜嗨| 久久av免费一区| 欧洲专线二区三区| 亚洲免费不卡| 在线免费观看日本欧美爱情大片| 国产盗摄视频在线观看| 伊人影院久久| 国产91在线视频观看| 亚洲女同同性videoxma| 日本va中文字幕| 国模大尺度一区二区三区| 粗大的内捧猛烈进出视频| 成人精品视频一区二区三区| 欲求不满的岳中文字幕| 国产亚洲一区二区三区在线观看| 神马久久久久久久久久久 | 青娱乐在线视频免费观看| 亚洲福利一二三区| 亚洲国产精品无码久久久| 欧美久久婷婷综合色| www.蜜臀av| 亚洲精品一区二区三区婷婷月| 国产在线观看网站| 久久久999精品视频| 国产91足控脚交在线观看| 欧美资源在线观看| 亚洲电影二区| 精品综合在线| 91中文字幕精品永久在线| 大陆av在线播放| 日韩二区在线观看| 永久免费看片在线观看| 91蜜桃视频在线| 性生交大片免费全黄| 欧美日韩免费看| 97超碰人人草| 精品偷拍一区二区三区在线看| 伊人免费在线| 97在线观看视频国产| 免费成人毛片| 精品国产乱码久久久久久郑州公司| 日韩av自拍| 热99这里只有精品| 久草这里只有精品视频| 人妻在线日韩免费视频| 亚洲色图一区二区| 天堂网视频在线| 精品久久久久一区| 日本在线免费网| 4438全国成人免费| 欧美视频精品全部免费观看| 欧美亚州在线观看| 在线欧美一区| 亚洲妇熟xx妇色黄蜜桃| 久久婷婷色综合| 久久无码精品丰满人妻| 欧美日韩国产综合草草| 欧美美女搞黄| 性色av一区二区三区红粉影视| 99久久99九九99九九九| 欧美日韩在线精品| 亚洲美女毛片| 亚洲国产欧美日韩在线| 国产精品久久久久久久岛一牛影视 | 色综合av在线| www日本视频| x99av成人免费| 全球最大av网站久久| 久久伊人一区二区| 亚洲日本黄色| 中文字幕99页| 亚洲自拍偷拍麻豆| 国产夫妻性生活视频| 精品久久久999| 免费视频成人| 亚洲春色在线| 日韩精品一二三| 欧美熟妇一区二区| 精品美女永久免费视频| 韩国中文字幕hd久久精品| 久久91亚洲精品中文字幕奶水| 日韩成人一区| 一区二区不卡在线视频 午夜欧美不卡' | 久久99国产综合精品女同| 激情视频亚洲| 国产一区一区三区| 激情成人午夜视频| 亚洲一区电影在线观看| 91精品一区二区三区久久久久久| 三区四区在线视频| 国产视频福利一区| 婷婷亚洲图片| 91亚洲一区二区| 亚洲精品老司机| 亚洲精品久久久久久久久久久久久久| 欧美大肥婆大肥bbbbb| 视频亚洲一区二区| 日韩国产成人无码av毛片| 成人国产视频在线观看| 国产无码精品在线观看| 日韩精品一区二区三区第95| 第84页国产精品| 日韩精品一区二区三区外面| 免费看黄色91| 粉嫩av性色av蜜臀av网站| 日韩欧美中文字幕精品| 成av人片在线观看www| 欧美二区在线| 蜜桃一区二区三区在线| 亚洲波多野结衣| 精品国产电影一区二区| 日本在线高清| 亚洲国产精品久久久久婷婷老年 | 欧美性色欧美a在线播放| 午夜伦理在线| 91精品国产一区二区三区动漫| 国产精品第十页| 波多野结衣av在线免费观看| 欧美色中文字幕| а天堂中文在线官网| 国产亚洲情侣一区二区无| 免费看黄裸体一级大秀欧美| 国产又粗又黄又猛| 日韩一区二区三区av| 不卡专区在线| 杨幂一区欧美专区| 国产成人三级在线观看| 亚洲大片免费观看| 久久色精品视频| 欧美大奶一区二区| 日本不卡一区在线| 亚洲国产中文字幕| 国产高清在线| 99re视频在线播放| 秋霞影院一区二区| 久久精品国产亚洲av无码娇色| 亚洲欧美变态国产另类| 精品999日本久久久影院| 亚洲 高清 成人 动漫| 国产精品久线观看视频| 少妇又色又爽又黄的视频| 国产女人18毛片水18精品| 国内精品美女在线观看| 精品手机在线视频| 亚洲国产欧美在线成人app |