This commit is contained in:
2026-04-24 15:42:54 +09:00
parent be4c383b6f
commit cd38fd49e2
18 changed files with 11609 additions and 235 deletions

View File

@@ -30,10 +30,12 @@ async function train() {
console.log(`Training with ${trainFiles.length} files...`);
// 학습 로직 (단순화된 경사 하강법 또는 반복 최적화)
// 학습 로직 (Sigmoid + [1, 12] scaling)
const sigmoid = (x: number) => 1 / (1 + Math.exp(-x));
let error = Infinity;
let iterations = 0;
while (error > margin && iterations < 100) {
while (error > margin && iterations < 10) { // Spec에 따라 10번 반복
let totalError = 0;
let count = 0;
@@ -48,24 +50,32 @@ async function train() {
if (!course) continue;
const target = records.find((r: any) => r.songno === songno && (r.diff === (diff === 'oni' ? 'oni' : 'ura')));
if (!target) {
// console.log(`[!] No target for ${songno} diff=${diff}`);
continue;
}
if (!target) continue;
const factors = factorize(course);
const prediction = Object.keys(factors).reduce((sum, key) =>
sum + (factors[key as keyof Factors] * weights[key as keyof Factors]), 0);
// 가중치 적용 전 정규화 (임의 값으로 가정)
const normalizedFactors = {
physical_density: Math.min(factors.physical_density / 20, 1),
stamina_requirement: Math.min(factors.stamina_requirement, 1),
pattern_complexity: Math.min(factors.pattern_complexity, 1),
rhythmic_complexity: Math.min(factors.rhythmic_complexity, 1),
reading_gimmick: Math.min(factors.reading_gimmick, 1)
};
const rawPrediction = Object.keys(normalizedFactors).reduce((sum, key) =>
sum + (normalizedFactors[key as keyof Factors] * weights[key as keyof Factors]), 0);
const prediction = (sigmoid(rawPrediction) * 11) + 1; // [1, 12]
const targetValue = parseFloat(target.);
const diff_val = targetValue - prediction;
totalError += Math.abs(diff_val);
count++;
// 가중치 업데이트
// 가중치 업데이트 (간단한 경사 하강법)
for (const key in weights) {
const k = key as keyof Factors;
weights[k] += diff_val * factors[k] * 0.05; // 학습률 조정
weights[k] += diff_val * normalizedFactors[k] * 0.01;
}
}
}