| | |
| |
|
| | export function generateRunNames(count) { |
| | const adjectives = [ |
| | 'ancient', 'brave', 'calm', 'clever', 'crimson', 'daring', 'eager', 'fearless', |
| | 'gentle', 'glossy', 'golden', 'hidden', 'icy', 'jolly', 'lively', 'mighty', |
| | 'noble', 'proud', 'quick', 'silent', 'swift', 'tiny', 'vivid', 'wild' |
| | ]; |
| | const nouns = [ |
| | 'river', 'mountain', 'harbor', 'forest', 'valley', 'ocean', 'meadow', 'desert', |
| | 'island', 'canyon', 'harbor', 'trail', 'summit', 'delta', 'lagoon', 'ridge', |
| | 'tundra', 'reef', 'plateau', 'prairie', 'grove', 'bay', 'dune', 'cliff' |
| | ]; |
| | const used = new Set(); |
| | const names = []; |
| | const pick = (arr) => arr[Math.floor(Math.random() * arr.length)]; |
| | |
| | while (names.length < count) { |
| | const name = `${pick(adjectives)}-${pick(nouns)}-${Math.floor(1 + Math.random() * 7)}`; |
| | if (!used.has(name)) { |
| | used.add(name); |
| | names.push(name); |
| | } |
| | } |
| | return names; |
| | } |
| |
|
| | export function genCurves(n) { |
| | const quality = Math.random(); |
| | const good = quality > 0.66; |
| | const poor = quality < 0.33; |
| | const l0 = 2.0 + Math.random() * 4.5; |
| | const targetLoss = good |
| | ? l0 * (0.12 + Math.random() * 0.12) |
| | : (poor ? l0 * (0.35 + Math.random() * 0.25) : l0 * (0.22 + Math.random() * 0.16)); |
| | |
| | const phases = 1 + Math.floor(Math.random() * 3); |
| | const marksSet = new Set(); |
| | while (marksSet.size < phases - 1) { |
| | marksSet.add(Math.floor((0.25 + Math.random() * 0.5) * (n - 1))); |
| | } |
| | const marks = [0, ...Array.from(marksSet).sort((a, b) => a - b), n - 1]; |
| | |
| | let kLoss = 0.02 + Math.random() * 0.08; |
| | const loss = new Array(n); |
| | |
| | for (let seg = 0; seg < marks.length - 1; seg++) { |
| | const a = marks[seg]; |
| | const b = marks[seg + 1] || a + 1; |
| | |
| | for (let i = a; i <= b; i++) { |
| | const t = (i - a) / Math.max(1, (b - a)); |
| | const segTarget = targetLoss * Math.pow(0.85, seg); |
| | let v = l0 * Math.exp(-kLoss * (i + 1)); |
| | v = 0.6 * v + 0.4 * (l0 + (segTarget - l0) * (seg + t) / Math.max(1, (marks.length - 1))); |
| | const noiseAmp = (0.08 * l0) * (1 - 0.8 * (i / (n - 1))); |
| | v += (Math.random() * 2 - 1) * noiseAmp; |
| | if (Math.random() < 0.02) v += 0.15 * l0; |
| | loss[i] = Math.max(0, v); |
| | } |
| | kLoss *= 1.6; |
| | } |
| | |
| | const a0 = 0.1 + Math.random() * 0.35; |
| | const aMax = good |
| | ? (0.92 + Math.random() * 0.07) |
| | : (poor ? (0.62 + Math.random() * 0.14) : (0.8 + Math.random() * 0.1)); |
| | |
| | let kAcc = 0.02 + Math.random() * 0.08; |
| | const acc = new Array(n); |
| | |
| | for (let i = 0; i < n; i++) { |
| | let v = aMax - (aMax - a0) * Math.exp(-kAcc * (i + 1)); |
| | const noiseAmp = 0.04 * (1 - 0.8 * (i / (n - 1))); |
| | v += (Math.random() * 2 - 1) * noiseAmp; |
| | acc[i] = Math.max(0, Math.min(1, v)); |
| | if (marksSet.has(i)) kAcc *= 1.4; |
| | } |
| | |
| | const accGap = 0.02 + Math.random() * 0.06; |
| | const lossGap = 0.05 + Math.random() * 0.15; |
| | const accVal = new Array(n); |
| | const lossVal = new Array(n); |
| | |
| | let ofStart = Math.floor(((good ? 0.85 : 0.7) + (Math.random() * 0.15 - 0.05)) * (n - 1)); |
| | ofStart = Math.max(Math.floor(0.5 * (n - 1)), Math.min(Math.floor(0.95 * (n - 1)), ofStart)); |
| | |
| | for (let i = 0; i < n; i++) { |
| | let av = acc[i] - accGap + (Math.random() * 0.06 - 0.03); |
| | let lv = loss[i] * (1 + lossGap) + (Math.random() * 0.1 - 0.05) * Math.max(1, l0 * 0.2); |
| | if (i >= ofStart && !poor) { |
| | const t = (i - ofStart) / Math.max(1, (n - 1 - ofStart)); |
| | av -= 0.03 * t; |
| | lv += 0.12 * t * loss[i]; |
| | } |
| | accVal[i] = Math.max(0, Math.min(1, av)); |
| | lossVal[i] = Math.max(0, lv); |
| | } |
| | |
| | return { accTrain: acc, lossTrain: loss, accVal, lossVal }; |
| | } |
| |
|