시드

Seed

생성 시작점의 난수 발생기에 주는 정수 하나. 같은 시드 + 같은 설정이면 언제나 같은 이미지가 나옵니다.

다른 이름: Random seedNoise seed
···
html
<div class="wrap">
  <canvas id="cv"></canvas>
  <div class="panel"><span class="lblseed">seed <b id="seedval">-</b></span><span class="tag" id="tag"></span></div>
</div>
css
.wrap{position:relative;width:100%;height:100%}
#cv{position:absolute;inset:0;width:100%;height:100%}
.panel{position:absolute;top:10px;left:10px;right:10px;z-index:2;display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:7px 10px;border-radius:10px;background:rgba(13,13,18,0.55);backdrop-filter:blur(6px);border:1px solid rgba(255,255,255,0.15)}
.lblseed{font-family:ui-monospace,monospace;font-size:11.5px;color:#f1f0ec}
.lblseed b{color:var(--accent)}
.tag{font-size:10.5px;font-weight:700;color:#b7b7c2}
js
const cv = document.getElementById('cv'), ctx = cv.getContext('2d');
const seedval = document.getElementById('seedval'), tag = document.getElementById('tag');
function fit() { const dpr = Math.min(devicePixelRatio || 1, 2); cv.width = innerWidth * dpr; cv.height = innerHeight * dpr; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); }
addEventListener('resize', fit); fit();

function mulberry32(a) { return function () { a |= 0; a = a + 0x6D2B79F5 | 0; let t = Math.imul(a ^ a >>> 15, 1 | a); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; }; }

function scene(seed) {
  const w = innerWidth, h = innerHeight;
  const r = mulberry32(seed);
  const hue = Math.floor(r() * 360);
  const g = ctx.createLinearGradient(0, 0, 0, h);
  g.addColorStop(0, 'hsl(' + hue + ' 55% 68%)'); g.addColorStop(1, 'hsl(' + ((hue + 30) % 360) + ' 45% 36%)');
  ctx.fillStyle = g; ctx.fillRect(0, 0, w, h);
  ctx.beginPath(); ctx.arc(w * (0.2 + r() * 0.6), h * (0.18 + r() * 0.12), Math.min(w, h) * 0.07, 0, Math.PI * 2);
  ctx.fillStyle = 'hsl(' + ((hue + 180) % 360) + ' 85% 70%)'; ctx.fill();
  for (let l = 0; l < 3; l++) {
    ctx.beginPath(); ctx.moveTo(0, h);
    for (let i = 0; i <= 7; i++) { const x = w * i / 7; const y = h * (0.5 + l * 0.13) - r() * h * 0.1; ctx.lineTo(x, y); }
    ctx.lineTo(w, h); ctx.closePath();
    ctx.fillStyle = 'hsl(' + ((hue + l * 20) % 360) + ' 40% ' + (18 + l * 10) + '%)'; ctx.fill();
  }
}

const A = 48213, B = 91027;
let seedNow = A;
function step() {
  scene(seedNow); seedval.textContent = seedNow; tag.textContent = '생성됨';
  setTimeout(() => {
    scene(seedNow); tag.textContent = '같은 시드로 재생성 → 동일한 이미지';
    setTimeout(() => {
      seedNow = seedNow === A ? B : A;
      scene(seedNow); seedval.textContent = seedNow; tag.textContent = '시드 변경 → 다른 이미지';
      setTimeout(step, 2000);
    }, 1800);
  }, 1800);
}
step();

확산 모델은 순수한 노이즈 텐서에서 출발해서 그걸 점점 이미지로 다듬어 갑니다. 그 시작 노이즈는 "무작위"처럼 보이지만 실제로는 의사난수 생성기가 만든 값이고, 이 생성기는 정수 하나(시드)로 완전히 결정됩니다. 그래서 시드를 고정하면 겉보기엔 무작위인 과정 전체가 그대로 재현됩니다.

이 성질은 비교 실험에 유용합니다. 시드를 고정한 채 프롬프트나 CFG 스케일 같은 다른 값만 바꾸면, 결과 차이가 그 값 때문인지 아니면 그냥 다른 노이즈 때문인지 헷갈리지 않고 비교할 수 있습니다. 마음에 드는 결과가 나오면 시드를 적어두고 나중에 다시 불러올 수도 있습니다.

다만 시드 재현성은 절대적이지 않습니다. 샘플러 종류, 연산 정밀도, 심지어 실행 하드웨어가 달라지면 같은 시드를 넣어도 미세하게 다른 결과가 나올 수 있습니다 — 같은 코드·같은 환경 안에서만 재현이 보장된다고 보는 편이 안전합니다.

아래 데모는 실제 모델 대신, 시드를 입력받는 결정적 의사난수 생성기(mulberry32)로 절차적 그림을 그려서 "같은 시드 = 같은 그림, 다른 시드 = 다른 그림"을 직접 보여주는 시뮬레이션입니다.

언제 쓰나

파라미터 하나의 효과를 다른 요인과 분리해서 보고 싶을 때 시드를 고정합니다. 다양한 결과를 계속 탐색하고 싶을 때는 반대로 매번 무작위 시드를 씁니다.