Fix inverted sign in formal/informal LDA analysis gradient
The model (analysis/bicorder_model.json) maps a positive LDA score to cluster 2 = Institutional/Bureaucratic = "formal", but ldaScoreToScale added the score (5 + score*4/3), sending formal/institutional protocols toward 9 (informal) and vice versa. bicorder.json defines this gradient as 1 = formal, 9 = informal, so the score must be subtracted. - Flip the sign: value = 5 - (ldaScore * 4/3); correct the doc comment to state the model's actual sign convention - Rename calculateBureaucratic -> calculateFormalInformal and update the stale analysisOrder comment, matching bicorder.json's formal/informal terms Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+22
-17
@@ -60,8 +60,8 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Analysis screens (shown in both shortform and longform)
|
// Analysis screens (shown in both shortform and longform)
|
||||||
// Show useful/not-useful gradient first (index 3), then the others
|
// Show the useful gradient first (index 3), then the others
|
||||||
const analysisOrder = [3, 0, 1, 2]; // useful/not-useful, hardness, polarization, bureaucratic
|
const analysisOrder = [3, 0, 1, 2]; // useful, hardness, polarization, formal/informal
|
||||||
analysisOrder.forEach((index) => {
|
analysisOrder.forEach((index) => {
|
||||||
screens.push({ type: 'analysis', index, gradient: data.analysis[index] });
|
screens.push({ type: 'analysis', index, gradient: data.analysis[index] });
|
||||||
});
|
});
|
||||||
@@ -303,25 +303,30 @@
|
|||||||
|
|
||||||
function ldaScoreToScale(ldaScore: number | null): number | null {
|
function ldaScoreToScale(ldaScore: number | null): number | null {
|
||||||
/**
|
/**
|
||||||
* Convert LDA score to 1-9 scale.
|
* Convert LDA score to the analysis[2] "formal vs informal" 1-9 scale.
|
||||||
* LDA scores typically range from -4 to +4 (8 range)
|
* LDA scores typically range from -4 to +4 (8 range); target is 1-9.
|
||||||
* Target scale is 1 to 9 (8 range)
|
|
||||||
*
|
*
|
||||||
* Formula: value = 5 + (ldaScore * 4/3)
|
* The model's sign convention (see analysis/bicorder_model.json):
|
||||||
* - LDA -3 or less → 1 (bureaucratic)
|
* positive LDA → cluster 2 = Institutional/Bureaucratic = "formal"
|
||||||
* - LDA 0 → 5 (boundary)
|
* negative LDA → cluster 1 = Relational/Cultural = "informal"
|
||||||
* - LDA +3 or more → 9 (relational)
|
* bicorder.json defines this gradient as 1 = formal, 9 = informal, so a
|
||||||
|
* positive LDA score must map toward 1 (formal). The score is therefore
|
||||||
|
* subtracted, not added.
|
||||||
|
*
|
||||||
|
* Formula: value = 5 - (ldaScore * 4/3)
|
||||||
|
* - LDA +3 or more → 1 (formal / institutional / bureaucratic)
|
||||||
|
* - LDA 0 → 5 (boundary, characteristics of both families)
|
||||||
|
* - LDA -3 or less → 9 (informal / relational / cultural)
|
||||||
*/
|
*/
|
||||||
if (ldaScore === null) return null;
|
if (ldaScore === null) return null;
|
||||||
|
|
||||||
// Scale: value = 5 + (ldaScore * 1.33)
|
const value = 5 - (ldaScore * 4.0 / 3.0);
|
||||||
const value = 5 + (ldaScore * 4.0 / 3.0);
|
|
||||||
|
|
||||||
// Clamp to 1-9 range and round
|
// Clamp to 1-9 range and round
|
||||||
return Math.round(Math.max(1, Math.min(9, value)));
|
return Math.round(Math.max(1, Math.min(9, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateBureaucratic(): number | null {
|
function calculateFormalInformal(): number | null {
|
||||||
// Collect all diagnostic gradients with their set and gradient info
|
// Collect all diagnostic gradients with their set and gradient info
|
||||||
const ratings: Record<string, number> = {};
|
const ratings: Record<string, number> = {};
|
||||||
|
|
||||||
@@ -329,7 +334,7 @@
|
|||||||
const setName = diagnosticSet.set_name;
|
const setName = diagnosticSet.set_name;
|
||||||
diagnosticSet.gradients.forEach((gradient) => {
|
diagnosticSet.gradients.forEach((gradient) => {
|
||||||
if (gradient.value !== null) {
|
if (gradient.value !== null) {
|
||||||
// Create dimension name in format: SetName_left_vs_right
|
// Dimension name must match the model's keys: SetName_left_vs_right
|
||||||
const dimensionName = `${setName}_${gradient.term_left}_vs_${gradient.term_right}`;
|
const dimensionName = `${setName}_${gradient.term_left}_vs_${gradient.term_right}`;
|
||||||
ratings[dimensionName] = gradient.value;
|
ratings[dimensionName] = gradient.value;
|
||||||
}
|
}
|
||||||
@@ -343,10 +348,10 @@
|
|||||||
// Get prediction from classifier (need detailed: true to get ldaScore)
|
// Get prediction from classifier (need detailed: true to get ldaScore)
|
||||||
const result = classifier.predict(ratings, { detailed: true });
|
const result = classifier.predict(ratings, { detailed: true });
|
||||||
|
|
||||||
// Convert LDA score to 1-9 scale
|
// Convert LDA score to the 1-9 formal/informal scale
|
||||||
return ldaScoreToScale(result.ldaScore);
|
return ldaScoreToScale(result.ldaScore);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error calculating bureaucratic/relational score:', error);
|
console.error('Error calculating formal/informal score:', error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -362,8 +367,8 @@
|
|||||||
// Polarized/Centrist
|
// Polarized/Centrist
|
||||||
data.analysis[1].value = calculatePolarization();
|
data.analysis[1].value = calculatePolarization();
|
||||||
} else if (index === 2) {
|
} else if (index === 2) {
|
||||||
// Bureaucratic/Relational (LDA classifier)
|
// Formal/Informal (LDA classifier)
|
||||||
data.analysis[2].value = calculateBureaucratic();
|
data.analysis[2].value = calculateFormalInformal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user