akshaybabu06 commited on
Commit
aa31414
·
verified ·
1 Parent(s): a7102c6
Files changed (1) hide show
  1. README.md +236 -1
README.md CHANGED
@@ -15,4 +15,239 @@ tags:
15
  - CLI
16
  - JobSelect
17
  - JobAnalyze
18
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  - CLI
16
  - JobSelect
17
  - JobAnalyze
18
+ ---
19
+
20
+ # JobAnalyze 6k v1.0 Skill Classifier
21
+
22
+ A lightweight **multi-label** PyTorch model that predicts a fixed set of **skills/keywords** from a job description plus a provided **role** and **job type**.
23
+
24
+ This README documents the exact artifacts and behavior implemented in:
25
+
26
+ - `model/model.py` (training definition)
27
+ - `model/pred.py` (inference wrapper)
28
+ - `model/prep/data_prep.py` (feature creation)
29
+
30
+ Sample runs and evaluation numbers referenced from:
31
+
32
+ - `data/sample_data/test.txt`
33
+ - `data/sample_data/eval.txt`
34
+ - `data/sample_data/cli.txt`
35
+
36
+ ---
37
+
38
+ ## Model summary
39
+
40
+ ### Task type
41
+
42
+ - **Multi-label classification** (each skill is predicted independently)
43
+
44
+ ### Inputs
45
+
46
+ - `job_desc` (job description text)
47
+ - `role` (free text, appended)
48
+ - `job_type` / `type` (free text, appended)
49
+
50
+ These are concatenated during prediction as:
51
+
52
+ ```text
53
+ {job_desc} {role} {job_type}
54
+ ```
55
+
56
+ ### Features
57
+
58
+ - TF-IDF features created by `model/prep/data_prep.py` using:
59
+ - `TfidfVectorizer(max_features=150, stop_words='english', ngram_range=(1, 2), min_df=2)`
60
+ - Artifacts:
61
+ - `model/prep/vectorizer.pkl`
62
+ - `model/prep/label_vocab.json`
63
+ - `model/prep/prepared_data.npz`
64
+
65
+ ### Labels
66
+
67
+ - A fixed vocabulary of skills/keywords stored in `model/prep/label_vocab.json`
68
+ - In training artifacts:
69
+ - `NUM_LABELS = len(VOCAB)`
70
+ - In sample data: **48 Keywords/labels**
71
+
72
+ ### Network architecture (the “6k / 6000 parameter” model)
73
+
74
+ `model/model.py` defines a small feed-forward network:
75
+
76
+ - Linear(input_dim → hidden_dim=32)
77
+ - ReLU
78
+ - Dropout(p=0.3)
79
+ - Linear(hidden_dim=32 → num_labels)
80
+
81
+ The file name and training printout refer to the total parameter count computed at runtime.
82
+
83
+ ---
84
+
85
+ ## Training (model/model.py)
86
+
87
+ **Do not run `model/model.py` directly for day-to-day use.** It is designed to be executed via `pipeline.py` (and/or the notebooks).
88
+
89
+ Training uses:
90
+
91
+ - Loss: `torch.nn.BCEWithLogitsLoss(pos_weight=pos_weight)`
92
+ - `pos_weight` is computed per-label from the training set (class imbalance handling)
93
+ - Clamped with `max=10.0`
94
+ - Optimizer: `Adam(lr=1e-3, weight_decay=1e-4)`
95
+ - Epochs: `300`
96
+
97
+ ### Outputs (saved artifacts)
98
+
99
+ At the end of training, the following are written to `model_out/`:
100
+
101
+ - `model_out/skill_classifier.pt`
102
+ - `model_out/training_history.json`
103
+
104
+ The test suite asserts these exist (see `test/test_model.py`).
105
+
106
+ ---
107
+
108
+ ## Inference (model/pred.py)
109
+
110
+ `model/pred.py` exposes a prediction helper:
111
+
112
+ ```python
113
+ JobAnalyze_6k(job_desc, role="", job_type="", top_k=50) -> List[(str, float)]
114
+ ```
115
+
116
+ Key behavior:
117
+
118
+ - Loads artifacts from repo-relative paths:
119
+ - `model/prep/label_vocab.json`
120
+ - `model/prep/vectorizer.pkl`
121
+ - `model_out/skill_classifier.pt`
122
+ - Vectorizes the concatenated text with TF-IDF and produces logits through the trained network.
123
+ - Converts logits to probabilities with `sigmoid`.
124
+ - Ranks all labels by probability descending and returns the top results.
125
+
126
+ > Note: `top_k` is capped by the number of labels effectively returned from the ranked list (in the code, slicing is applied directly).
127
+
128
+ ---
129
+
130
+ ## Evaluation snapshot (from data/sample_data)
131
+
132
+ ### Micro/Macro F1
133
+
134
+ From `data/sample_data/eval.txt`:
135
+
136
+ - **Micro-F1: 0.624**
137
+ - **Macro-F1: 0.420**
138
+
139
+ ### Baseline comparison
140
+
141
+ Also from `data/sample_data/eval.txt`, baseline always predicts a fixed set of frequent labels:
142
+
143
+ - Baseline Micro-F1: **0.538**
144
+ - Baseline Macro-F1: **0.152**
145
+
146
+ The evaluation script prints:
147
+
148
+ > “Model meaningfully beats the naive baseline.”
149
+
150
+ ### Per-label and “trap” analysis
151
+
152
+ The evaluation output includes per-label precision/recall/F1 and an additional heuristic:
153
+
154
+ - “trap?” flags labels where the model does not perform better than a trivial always-zero expectation (within a small tolerance).
155
+
156
+ From `data/sample_data/eval.txt`:
157
+
158
+ - Right: **15**
159
+ - Wrong: **33**
160
+ - Total labels: **48**
161
+ - Keyword Accuracy: **31.25%**
162
+
163
+ ---
164
+
165
+ ## Example: single inference test (data/sample_data/test.txt)
166
+
167
+ `data/sample_data/test.txt` contains a job description plus:
168
+
169
+ - Role: **AI Engineer**
170
+ - Type: **Junior**
171
+
172
+ It lists **15 keys to be predicted**, including:
173
+
174
+ - Python, LLMs, LangGraph, MCP, GenAI, VectorDB, SQL, APIs, Docker, Agents, Github, CI/CD, Git, AWS/Azure, Prompt Engineering
175
+
176
+ Reported performance:
177
+
178
+ - Accuracy (recall): **93.34%** (14/15)
179
+
180
+ ---
181
+
182
+ ## Example: CLI output format (data/sample_data/cli.txt)
183
+
184
+ `cli/jobauto.py` uses `JobAnalyze_6k` from `model.pred` and prints:
185
+
186
+ - The job description provided
187
+ - Role and Type
188
+ - A ranked “TOP Skills” list as `{label} {probability}` plus a text bar
189
+
190
+ From `data/sample_data/cli.txt`, the top-ranked skills include (with example probabilities):
191
+
192
+ - apis ~0.78
193
+ - langgraph ~0.78
194
+ - vectordb ~0.76
195
+ - mcp ~0.75
196
+ - langchain ~0.74
197
+ - rag ~0.72
198
+
199
+ ---
200
+
201
+ ## Data prep artifacts (model/prep/data_prep.py)
202
+
203
+ `model/prep/data_prep.py` creates all required inputs for training and inference.
204
+
205
+ It:
206
+
207
+ 1. Loads cleaned job description dataset
208
+ 2. Normalizes and fixes known skill spelling issues (`SKILLS_FIX`)
209
+ 3. Applies synonym replacement using `model/prep/sym_map.py`
210
+ 4. Builds a multi-hot label vector for the vocabulary
211
+ 5. Vectorizes job text with TF-IDF
212
+ 6. Splits into train/test and saves:
213
+ - `prepared_data.npz`
214
+ - `label_vocab.json`
215
+ - `vectorizer.pkl`
216
+
217
+ ---
218
+
219
+ ## Reproducibility / how to use
220
+
221
+ ### Requirements (high level)
222
+
223
+ See `requirements.txt` and `pyproject.toml`.
224
+
225
+ ### Minimum artifacts required for prediction
226
+
227
+ For `model/pred.py` to work, these must exist:
228
+
229
+ - `model/prep/label_vocab.json`
230
+ - `model/prep/vectorizer.pkl`
231
+ - `model_out/skill_classifier.pt`
232
+
233
+ If any are missing, `model/pred.py` raises a `FileNotFoundError` with guidance.
234
+
235
+ ### Recommended workflow
236
+
237
+ - Run the full pipeline via `pipeline.py` (which coordinates data prep + training).
238
+ - Use `cli/jobauto.py` for interactive predictions.
239
+
240
+ ---
241
+
242
+ ## Notes on “JobAnalyze 6k”
243
+
244
+ Despite the “6k / 6000 parameter” naming, the true parameter count is computed dynamically in `model/model.py`.
245
+
246
+ The implementation is intentionally small:
247
+
248
+ - TF-IDF input features
249
+ - 1 hidden layer with 32 units
250
+ - Multi-label BCE loss with class imbalance reweighting
251
+
252
+ This design keeps inference fast and model size small while still providing meaningful gains over the naive baseline (see evaluation snapshot above).
253
+