Views
No views yet
1pip install git+https://github.com/rinnakk/japanese-stable-diffusion
2pip install diffusers==0.4.1
3sudo apt-get install git-lfs
4git clone https://huggingface.co/svjack/Stable-Diffusion-Pokemon-zhhuggingface-cli login1import torch
2import pandas as pd
3
4from torch import autocast
5from diffusers import LMSDiscreteScheduler
6
7import torch
8from transformers import BertForSequenceClassification, BertConfig, BertTokenizer, BertForTokenClassification
9from transformers import CLIPProcessor, CLIPModel
10import numpy as np
11
12from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion import *
13from japanese_stable_diffusion.pipeline_stable_diffusion import *
14
15class StableDiffusionPipelineWrapper(StableDiffusionPipeline):
16
17 @torch.no_grad()
18 def __call__(
19 self,
20 prompt: Union[str, List[str]],
21 height: int = 512,
22 width: int = 512,
23 num_inference_steps: int = 50,
24 guidance_scale: float = 7.5,
25 negative_prompt: Optional[Union[str, List[str]]] = None,
26 num_images_per_prompt: Optional[int] = 1,
27 eta: float = 0.0,
28 generator: Optional[torch.Generator] = None,
29 latents: Optional[torch.FloatTensor] = None,
30 output_type: Optional[str] = "pil",
31 return_dict: bool = True,
32 callback: Optional[Callable[[int, int, torch.FloatTensor], None]] = None,
33 callback_steps: Optional[int] = 1,
34 **kwargs,
35 ):
36 if isinstance(prompt, str):
37 batch_size = 1
38 elif isinstance(prompt, list):
39 batch_size = len(prompt)
40 else:
41 raise ValueError(f"`prompt` has to be of type `str` or `list` but is {type(prompt)}")
42
43 if height % 8 != 0 or width % 8 != 0:
44 raise ValueError(f"`height` and `width` have to be divisible by 8 but are {height} and {width}.")
45
46 if (callback_steps is None) or (
47 callback_steps is not None and (not isinstance(callback_steps, int) or callback_steps <= 0)
48 ):
49 raise ValueError(
50 f"`callback_steps` has to be a positive integer but is {callback_steps} of type"
51 f" {type(callback_steps)}."
52 )
53
54 # get prompt text embeddings
55 text_inputs = self.tokenizer(
56 prompt,
57 padding="max_length",
58 max_length=self.tokenizer.model_max_length,
59 return_tensors="pt",
60 )
61 text_input_ids = text_inputs.input_ids
62
63 if text_input_ids.shape[-1] > self.tokenizer.model_max_length:
64 removed_text = self.tokenizer.batch_decode(text_input_ids[:, self.tokenizer.model_max_length :])
65 logger.warning(
66 "The following part of your input was truncated because CLIP can only handle sequences up to"
67 f" {self.tokenizer.model_max_length} tokens: {removed_text}"
68 )
69 text_input_ids = text_input_ids[:, : self.tokenizer.model_max_length]
70 text_embeddings = self.text_encoder(text_input_ids.to(self.device))[0]
71
72 # duplicate text embeddings for each generation per prompt, using mps friendly method
73 bs_embed, seq_len, _ = text_embeddings.shape
74 text_embeddings = text_embeddings.repeat(1, num_images_per_prompt, 1)
75 text_embeddings = text_embeddings.view(bs_embed * num_images_per_prompt, seq_len, -1)
76
77 # here `guidance_scale` is defined analog to the guidance weight `w` of equation (2)
78 # of the Imagen paper: https://arxiv.org/pdf/2205.11487.pdf . `guidance_scale = 1`
79 # corresponds to doing no classifier free guidance.
80 do_classifier_free_guidance = guidance_scale > 1.0
81 # get unconditional embeddings for classifier free guidance
82 if do_classifier_free_guidance:
83 uncond_tokens: List[str]
84 if negative_prompt is None:
85 uncond_tokens = [""]
86 elif type(prompt) is not type(negative_prompt):
87 raise TypeError(
88 f"`negative_prompt` should be the same type to `prompt`, but got {type(negative_prompt)} !="
89 f" {type(prompt)}."
90 )
91 elif isinstance(negative_prompt, str):
92 uncond_tokens = [negative_prompt]
93 elif batch_size != len(negative_prompt):
94 raise ValueError(
95 f"`negative_prompt`: {negative_prompt} has batch size {len(negative_prompt)}, but `prompt`:"
96 f" {prompt} has batch size {batch_size}. Please make sure that passed `negative_prompt` matches"
97 " the batch size of `prompt`."
98 )
99 else:
100 uncond_tokens = negative_prompt
101
102 max_length = text_input_ids.shape[-1]
103 uncond_input = self.tokenizer(
104 uncond_tokens,
105 padding="max_length",
106 max_length=max_length,
107 truncation=True,
108 return_tensors="pt",
109 )
110 uncond_embeddings = self.text_encoder(uncond_input.input_ids.to(self.device))[0]
111
112 # duplicate unconditional embeddings for each generation per prompt, using mps friendly method
113 seq_len = uncond_embeddings.shape[1]
114 uncond_embeddings = uncond_embeddings.repeat(batch_size, num_images_per_prompt, 1)
115 uncond_embeddings = uncond_embeddings.view(batch_size * num_images_per_prompt, seq_len, -1)
116
117 # For classifier free guidance, we need to do two forward passes.
118 # Here we concatenate the unconditional and text embeddings into a single batch
119 # to avoid doing two forward passes
120 text_embeddings = torch.cat([uncond_embeddings, text_embeddings])
121
122 # get the initial random noise unless the user supplied it
123
124 # Unlike in other pipelines, latents need to be generated in the target device
125 # for 1-to-1 results reproducibility with the CompVis implementation.
126 # However this currently doesn't work in `mps`.
127 latents_shape = (batch_size * num_images_per_prompt, self.unet.in_channels, height // 8, width // 8)
128 latents_dtype = text_embeddings.dtype
129 if latents is None:
130 if self.device.type == "mps":
131 # randn does not work reproducibly on mps
132 latents = torch.randn(latents_shape, generator=generator, device="cpu", dtype=latents_dtype).to(
133 self.device
134 )
135 else:
136 latents = torch.randn(latents_shape, generator=generator, device=self.device, dtype=latents_dtype)
137 else:
138 if latents.shape != latents_shape:
139 raise ValueError(f"Unexpected latents shape, got {latents.shape}, expected {latents_shape}")
140 latents = latents.to(self.device)
141
142 # set timesteps
143 self.scheduler.set_timesteps(num_inference_steps)
144
145 # Some schedulers like PNDM have timesteps as arrays
146 # It's more optimized to move all timesteps to correct device beforehand
147 timesteps_tensor = self.scheduler.timesteps.to(self.device)
148
149 # scale the initial noise by the standard deviation required by the scheduler
150 latents = latents * self.scheduler.init_noise_sigma
151
152 # prepare extra kwargs for the scheduler step, since not all schedulers have the same signature
153 # eta (η) is only used with the DDIMScheduler, it will be ignored for other schedulers.
154 # eta corresponds to η in DDIM paper: https://arxiv.org/abs/2010.02502
155 # and should be between [0, 1]
156 accepts_eta = "eta" in set(inspect.signature(self.scheduler.step).parameters.keys())
157 extra_step_kwargs = {}
158 if accepts_eta:
159 extra_step_kwargs["eta"] = eta
160
161 for i, t in enumerate(self.progress_bar(timesteps_tensor)):
162 # expand the latents if we are doing classifier free guidance
163 latent_model_input = torch.cat([latents] * 2) if do_classifier_free_guidance else latents
164 latent_model_input = self.scheduler.scale_model_input(latent_model_input, t)
165
166 # predict the noise residual
167 ###text_embeddings
168 #print("before :" ,text_embeddings.shape)
169 eh_shape = text_embeddings.shape
170 if i == 0:
171 eh_pad = torch.zeros((eh_shape[0], eh_shape[1], 768 - 512))
172 eh_pad = eh_pad.to(self.device)
173 text_embeddings = torch.concat([text_embeddings, eh_pad], -1)
174
175 #print("after :" ,text_embeddings.shape)
176 noise_pred = self.unet(latent_model_input, t, encoder_hidden_states=text_embeddings).sample
177
178 # perform guidance
179 if do_classifier_free_guidance:
180 noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
181 noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)
182
183 # compute the previous noisy sample x_t -> x_t-1
184 latents = self.scheduler.step(noise_pred, t, latents, **extra_step_kwargs).prev_sample
185
186 # call the callback, if provided
187 if callback is not None and i % callback_steps == 0:
188 callback(i, t, latents)
189
190 latents = 1 / 0.18215 * latents
191 image = self.vae.decode(latents).sample
192
193 image = (image / 2 + 0.5).clamp(0, 1)
194
195 # we always cast to float32 as this does not cause significant overhead and is compatible with bfloa16
196 image = image.cpu().permute(0, 2, 3, 1).float().numpy()
197
198 if self.safety_checker is not None:
199 safety_checker_input = self.feature_extractor(self.numpy_to_pil(image), return_tensors="pt").to(
200 self.device
201 )
202 image, has_nsfw_concept = self.safety_checker(
203 images=image, clip_input=safety_checker_input.pixel_values.to(text_embeddings.dtype)
204 )
205 else:
206 has_nsfw_concept = None
207
208 if output_type == "pil":
209 image = self.numpy_to_pil(image)
210
211 if not return_dict:
212 return (image, has_nsfw_concept)
213
214 return StableDiffusionPipelineOutput(images=image, nsfw_content_detected=has_nsfw_concept)
215
216
217scheduler = LMSDiscreteScheduler(beta_start=0.00085, beta_end=0.012,
218 beta_schedule="scaled_linear", num_train_timesteps=1000)
219
220#pretrained_model_name_or_path = "zh_model_20000"
221#### sudo apt-get install git-lfs
222#### git clone https://huggingface.co/svjack/Stable-Diffusion-Pokemon-zh
223pretrained_model_name_or_path = "Stable-Diffusion-Pokemon-zh"
224
225tokenizer = BertTokenizer.from_pretrained(pretrained_model_name_or_path, subfolder = "tokenizer")
226text_encoder = BertForTokenClassification.from_pretrained(pretrained_model_name_or_path, subfolder = "text_encoder")
227
228vae = AutoencoderKL.from_pretrained(pretrained_model_name_or_path, subfolder="vae")
229unet = UNet2DConditionModel.from_pretrained(pretrained_model_name_or_path, subfolder="unet")
230
231tokenizer.model_max_length = 77
232pipeline_wrap = StableDiffusionPipelineWrapper(
233 text_encoder=text_encoder,
234 vae=vae,
235 unet=unet,
236 tokenizer=tokenizer,
237 scheduler=scheduler,
238 safety_checker=StableDiffusionSafetyChecker.from_pretrained("CompVis/stable-diffusion-safety-checker"),
239 feature_extractor=CLIPFeatureExtractor.from_pretrained("openai/clip-vit-base-patch32"),
240 )
241pipeline_wrap.safety_checker = lambda images, clip_input: (images, False)
242pipeline_wrap = pipeline_wrap.to("cuda")
243
244imgs = pipeline_wrap("一个头上戴着盆栽的卡通人物",
245 num_inference_steps = 100
246)
247image = imgs.images[0]
248
249image.save("output.png")

