A career recommender built on a PPMI skill graph and a two-layer Dijkstra + rank split. The model is on the page. The numbers you see are the same numbers the algorithm saw.
Starting from
Data entry · เจ้าหน้าที่บันทึกข้อมูล
15,000 THB · risk 95% · centrality 0.55
Junior data analyst
+20,000 THB · 1 hop · 3 shared skills
Layer 1 cost
0.060
Layer 2 score
+0.395
Path
data_entry → jda
Bridges
sql, excel, english
Each dot is a Thai occupation. The dashed line is the OLS fit of median wage on degree centrality — what the network predicts each job should pay. Dots below the line are paid less than their network position predicts.
PPMI(co_occurrence)153 postings → 46 skills → 129 edges. Edges with PMI ≤ 0 are dropped.
1 − clamp(direct + indirect)Direct overlap (min) + indirect PPMI bridge (0.4 hop decay). Output ∈ [0, 1].
α·dist_norm + γ·risk_normSingle-source min-cost path. Non-negative weights keep the algorithm correct.
β·wage_norm − path_cost − γ₂·riskScore targets by wage gain, penalised by path cost and target risk. Top N returned.
The recommender is split into four explicit layers. Each one is auditable, testable, and shown in the UI so you can follow the numbers from the page back to the math.
“The naive formula α·dist − β·wage + γ·risk has two bugs. The two-layer split avoids both.”
“Edge cost is non-negative (α·dist_norm + γ·risk_norm). That's the invariant that makes Dijkstra safe.”
“PPMI = max(0, log P(a,b) / (P(a)·P(b))). Drop sub-independence pairs.”
“Wage gap = (predicted − actual) / predicted. Positive gap = underpaid signal.”