finipher commited on
Commit
2f41bc6
·
verified ·
1 Parent(s): 3ae7e9a
README.md ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: other
3
+ base_model: sentence-transformers/all-MiniLM-L6-v2
4
+ datasets:
5
+ - finipher/finipher-us-tax-document-classifier
6
+ pipeline_tag: text-classification
7
+ language:
8
+ - en
9
+ tags:
10
+ - finance
11
+ - tax
12
+ - document-classification
13
+ ---
14
+
15
+ # Finipher tax document classifier v1.0.0
16
+
17
+ Names what a US tax or financial document is (W-2, 1098, 1099-INT, mortgage statement, paystub,
18
+ brokerage statement and so on) from the first 128 tokens of its extracted text. 95 labels.
19
+
20
+ It is a small head on a frozen MiniLM encoder. The head only works with the exact encoder it was
21
+ trained on, so this repo carries its own copy of that encoder (`model.safetensors`, SHA-256
22
+ `96d95c25…`). That file also holds a transaction output layer, which this model ignores.
23
+
24
+ Internal names: checkpoint `finance-multitask-minilm-two-head-v2`; head artifact
25
+ `tax-document-head-20261027-v1.1-category-encoder` (stored inside `tax_document_head_config.json`).
26
+
27
+ ## How to use
28
+
29
+ The head is custom, so load it with this code (the same steps Finipher runs in production):
30
+
31
+ ```python
32
+ from huggingface_hub import snapshot_download
33
+ from safetensors.torch import load_file
34
+ from transformers import AutoModel, AutoTokenizer
35
+ import json, torch
36
+
37
+ path = snapshot_download("finipher/finipher-tax-document-classifier", revision="v1.0.0")
38
+ tok = AutoTokenizer.from_pretrained(path)
39
+ enc = AutoModel.from_pretrained(path).eval() # ignores the transaction output layer
40
+ head = load_file(f"{path}/tax_document_head.safetensors")
41
+ cfg = json.load(open(f"{path}/tax_document_head_config.json"))
42
+ labels = [cfg["id2label"][str(i)] for i in range(cfg["num_labels"])]
43
+
44
+ def classify(text: str):
45
+ x = tok([text.strip()[:4000]], truncation=True, max_length=128, return_tensors="pt")
46
+ with torch.inference_mode():
47
+ h = enc(**x).last_hidden_state
48
+ m = x["attention_mask"].unsqueeze(-1).float()
49
+ e = torch.nn.functional.normalize((h * m).sum(1) / m.sum(1), dim=-1)
50
+ p = torch.softmax(e @ head["weight"].T + head["bias"], dim=-1)[0]
51
+ i = int(p.argmax())
52
+ return labels[i], float(p[i]), float(p[i]) >= cfg["review_threshold"] # 0.76
53
+ ```
54
+
55
+ The third value says whether the label is confident enough to use (0.76 or higher). Below that,
56
+ send the document to a person to review. `OTHER_TAX_FORM` and `UNKNOWN_DOCUMENT` always need review.
57
+
58
+ ## Results
59
+
60
+ Measured offline through Finipher's production code:
61
+ - Test set (2,531 documents): 98.5%.
62
+ - Same set with the titles cut off (1,203): 94.7%.
63
+ - Blind probes (33): 90.9%.
64
+
65
+ ## Known mistakes
66
+
67
+ - Credit card statement CSV exports read as BANK_STATEMENT (confidence 0.51–0.71, so usually sent to review).
68
+
69
+ ## Training data
70
+
71
+ `finipher/finipher-us-tax-document-classifier` at revision `92c67c9` (v1.1.0), licensed CC-BY-4.0.
72
+ The encoder underneath also comes from the transaction model, whose training data is still to be
73
+ confirmed. This repo stays private until that is documented.
74
+
75
+ ## Use
76
+
77
+ The output names a document type. It is not tax or financial advice.
78
+
79
+ ## Files and SHA-256
80
+
81
+ | File | SHA-256 |
82
+ |---|---|
83
+ | `config.json` | `6b8c456706017e7cbddd8a4826a88746294100336be5aa9e40f7730890f1b72b` |
84
+ | `model.safetensors` | `96d95c2520f9b8cee0a3e85e1440f541420c4c043e18a0c4579943e08e91a5a3` |
85
+ | `tokenizer.json` | `41b9d12a4c559e4098f30173bc0f76d092c43d7b1f873e7027da45a256f30f87` |
86
+ | `tokenizer_config.json` | `1128dd50ff3f913671a9405619c1bd8f9e9ddc28f62257cb94ed70683590b715` |
87
+ | `tax_document_head.safetensors` | `bb60aaad3734afda9120757dec4e2ed60ae04c6ba93f5993a3cb0c893ee4ac35` |
88
+ | `tax_document_head_config.json` | `41600002856c26fc30bb47d2c6e40b3c8a0352b77220c1e21c3d6c3e57594c8b` |
config.json ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_cross_attention": false,
3
+ "architectures": [
4
+ "BertForSequenceClassification"
5
+ ],
6
+ "attention_probs_dropout_prob": 0.1,
7
+ "bos_token_id": null,
8
+ "classifier_dropout": null,
9
+ "dtype": "float32",
10
+ "eos_token_id": null,
11
+ "gradient_checkpointing": false,
12
+ "hidden_act": "gelu",
13
+ "hidden_dropout_prob": 0.1,
14
+ "hidden_size": 384,
15
+ "id2label": {
16
+ "0": "Education",
17
+ "1": "Entertainment",
18
+ "2": "Fees",
19
+ "3": "Groceries",
20
+ "4": "Healthcare",
21
+ "5": "Income",
22
+ "6": "Insurance",
23
+ "7": "Mortgage",
24
+ "8": "Personal Care",
25
+ "9": "Rent",
26
+ "10": "Restaurants",
27
+ "11": "Shopping",
28
+ "12": "Subscription",
29
+ "13": "Transfer",
30
+ "14": "Transportation",
31
+ "15": "Travel",
32
+ "16": "Utilities"
33
+ },
34
+ "initializer_range": 0.02,
35
+ "intermediate_size": 1536,
36
+ "is_decoder": false,
37
+ "label2id": {
38
+ "Education": 0,
39
+ "Entertainment": 1,
40
+ "Fees": 2,
41
+ "Groceries": 3,
42
+ "Healthcare": 4,
43
+ "Income": 5,
44
+ "Insurance": 6,
45
+ "Mortgage": 7,
46
+ "Personal Care": 8,
47
+ "Rent": 9,
48
+ "Restaurants": 10,
49
+ "Shopping": 11,
50
+ "Subscription": 12,
51
+ "Transfer": 13,
52
+ "Transportation": 14,
53
+ "Travel": 15,
54
+ "Utilities": 16
55
+ },
56
+ "layer_norm_eps": 1e-12,
57
+ "max_position_embeddings": 512,
58
+ "model_type": "bert",
59
+ "num_attention_heads": 12,
60
+ "num_hidden_layers": 6,
61
+ "pad_token_id": 0,
62
+ "position_embedding_type": "absolute",
63
+ "problem_type": "single_label_classification",
64
+ "tie_word_embeddings": true,
65
+ "transformers_version": "5.19.0",
66
+ "type_vocab_size": 2,
67
+ "use_cache": true,
68
+ "vocab_size": 30522
69
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:96d95c2520f9b8cee0a3e85e1440f541420c4c043e18a0c4579943e08e91a5a3
3
+ size 90891060
tax_document_head.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bb60aaad3734afda9120757dec4e2ed60ae04c6ba93f5993a3cb0c893ee4ac35
3
+ size 146444
tax_document_head_config.json ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "artifact_version": "tax-document-head-20261027-v1.1-category-encoder",
3
+ "architecture": "frozen transaction MiniLM encoder + 95-way tax document head",
4
+ "base_model": "sentence-transformers/all-MiniLM-L6-v2",
5
+ "base_model_safetensors_sha256": "96d95c2520f9b8cee0a3e85e1440f541420c4c043e18a0c4579943e08e91a5a3",
6
+ "dataset": "finipher/finipher-us-tax-document-classifier",
7
+ "dataset_revision": "92c67c932c479e5f5944e5b5687aa327569e5de7",
8
+ "dataset_license": "CC-BY-4.0",
9
+ "num_labels": 95,
10
+ "hidden_size": 384,
11
+ "max_length": 128,
12
+ "pooling": "attention_mask_mean_l2_normalized",
13
+ "logit_scale_baked_into_weight": 10.0,
14
+ "selected_weight_decay": 1e-05,
15
+ "encoder_frozen": true,
16
+ "transaction_head_frozen": true,
17
+ "review_threshold": 0.76,
18
+ "label2id": {
19
+ "1040": 0,
20
+ "1040-ES": 1,
21
+ "1040-NR": 2,
22
+ "1040-SR": 3,
23
+ "1040-X": 4,
24
+ "1041": 5,
25
+ "1065": 6,
26
+ "1095-A": 7,
27
+ "1095-B": 8,
28
+ "1095-C": 9,
29
+ "1098": 10,
30
+ "1098-C": 11,
31
+ "1098-E": 12,
32
+ "1098-T": 13,
33
+ "1099-A": 14,
34
+ "1099-B": 15,
35
+ "1099-C": 16,
36
+ "1099-DA": 17,
37
+ "1099-DIV": 18,
38
+ "1099-G": 19,
39
+ "1099-INT": 20,
40
+ "1099-K": 21,
41
+ "1099-MISC": 22,
42
+ "1099-NEC": 23,
43
+ "1099-OID": 24,
44
+ "1099-Q": 25,
45
+ "1099-R": 26,
46
+ "1099-S": 27,
47
+ "1099-SA": 28,
48
+ "1116": 29,
49
+ "1120-S": 30,
50
+ "2441": 31,
51
+ "2555": 32,
52
+ "2848": 33,
53
+ "3520": 34,
54
+ "4506-T": 35,
55
+ "4868": 36,
56
+ "5498": 37,
57
+ "5498-ESA": 38,
58
+ "5498-SA": 39,
59
+ "5695": 40,
60
+ "709": 41,
61
+ "709-NA": 42,
62
+ "8283": 43,
63
+ "8332": 44,
64
+ "8889": 45,
65
+ "8936": 46,
66
+ "8938": 47,
67
+ "8949": 48,
68
+ "8962": 49,
69
+ "ANNUAL_GIVING_STATEMENT": 50,
70
+ "BANK_STATEMENT": 51,
71
+ "BUSINESS_SALES_LEDGER": 52,
72
+ "CHARITABLE_PLEDGE_NOTICE": 53,
73
+ "CHARITY_EVENT_RECEIPT": 54,
74
+ "CREDIT_CARD_STATEMENT": 55,
75
+ "DONATION_APPEAL": 56,
76
+ "ESTIMATED_TAX_PAYMENT_CONFIRMATION": 57,
77
+ "FOREIGN_GIFT_RECORD": 58,
78
+ "GIFT_TRANSFER_AGREEMENT": 59,
79
+ "K-1-1041": 60,
80
+ "K-1-1065": 61,
81
+ "K-1-1120-S": 62,
82
+ "MEDICAL_RECEIPT": 63,
83
+ "NONCASH_DONATION_ACKNOWLEDGMENT": 64,
84
+ "PERSONAL_GIFT_LETTER": 65,
85
+ "PURCHASE_RECEIPT": 66,
86
+ "RENTAL_INCOME_RECORD": 67,
87
+ "SCHEDULE-A": 68,
88
+ "SCHEDULE-B": 69,
89
+ "SCHEDULE-C": 70,
90
+ "SCHEDULE-D": 71,
91
+ "SCHEDULE-E": 72,
92
+ "SCHEDULE-F": 73,
93
+ "SCHEDULE-SE": 74,
94
+ "TAX_INSTRUCTIONS": 75,
95
+ "UNKNOWN_DOCUMENT": 76,
96
+ "VEHICLE_DONATION_ACKNOWLEDGMENT": 77,
97
+ "W-2": 78,
98
+ "W-2C": 79,
99
+ "W-2G": 80,
100
+ "W-4": 81,
101
+ "W-9": 82,
102
+ "MORTGAGE_STATEMENT": 83,
103
+ "LOAN_STATEMENT": 84,
104
+ "BROKERAGE_STATEMENT": 85,
105
+ "RETIREMENT_ACCOUNT_STATEMENT": 86,
106
+ "HSA_ACCOUNT_STATEMENT": 87,
107
+ "PAYSTUB": 88,
108
+ "INSURANCE_DOCUMENT": 89,
109
+ "CRYPTO_TAX_REPORT": 90,
110
+ "PROPERTY_TAX_BILL": 91,
111
+ "PROFIT_AND_LOSS_STATEMENT": 92,
112
+ "CONSOLIDATED_1099": 93,
113
+ "OTHER_TAX_FORM": 94
114
+ },
115
+ "id2label": {
116
+ "0": "1040",
117
+ "1": "1040-ES",
118
+ "2": "1040-NR",
119
+ "3": "1040-SR",
120
+ "4": "1040-X",
121
+ "5": "1041",
122
+ "6": "1065",
123
+ "7": "1095-A",
124
+ "8": "1095-B",
125
+ "9": "1095-C",
126
+ "10": "1098",
127
+ "11": "1098-C",
128
+ "12": "1098-E",
129
+ "13": "1098-T",
130
+ "14": "1099-A",
131
+ "15": "1099-B",
132
+ "16": "1099-C",
133
+ "17": "1099-DA",
134
+ "18": "1099-DIV",
135
+ "19": "1099-G",
136
+ "20": "1099-INT",
137
+ "21": "1099-K",
138
+ "22": "1099-MISC",
139
+ "23": "1099-NEC",
140
+ "24": "1099-OID",
141
+ "25": "1099-Q",
142
+ "26": "1099-R",
143
+ "27": "1099-S",
144
+ "28": "1099-SA",
145
+ "29": "1116",
146
+ "30": "1120-S",
147
+ "31": "2441",
148
+ "32": "2555",
149
+ "33": "2848",
150
+ "34": "3520",
151
+ "35": "4506-T",
152
+ "36": "4868",
153
+ "37": "5498",
154
+ "38": "5498-ESA",
155
+ "39": "5498-SA",
156
+ "40": "5695",
157
+ "41": "709",
158
+ "42": "709-NA",
159
+ "43": "8283",
160
+ "44": "8332",
161
+ "45": "8889",
162
+ "46": "8936",
163
+ "47": "8938",
164
+ "48": "8949",
165
+ "49": "8962",
166
+ "50": "ANNUAL_GIVING_STATEMENT",
167
+ "51": "BANK_STATEMENT",
168
+ "52": "BUSINESS_SALES_LEDGER",
169
+ "53": "CHARITABLE_PLEDGE_NOTICE",
170
+ "54": "CHARITY_EVENT_RECEIPT",
171
+ "55": "CREDIT_CARD_STATEMENT",
172
+ "56": "DONATION_APPEAL",
173
+ "57": "ESTIMATED_TAX_PAYMENT_CONFIRMATION",
174
+ "58": "FOREIGN_GIFT_RECORD",
175
+ "59": "GIFT_TRANSFER_AGREEMENT",
176
+ "60": "K-1-1041",
177
+ "61": "K-1-1065",
178
+ "62": "K-1-1120-S",
179
+ "63": "MEDICAL_RECEIPT",
180
+ "64": "NONCASH_DONATION_ACKNOWLEDGMENT",
181
+ "65": "PERSONAL_GIFT_LETTER",
182
+ "66": "PURCHASE_RECEIPT",
183
+ "67": "RENTAL_INCOME_RECORD",
184
+ "68": "SCHEDULE-A",
185
+ "69": "SCHEDULE-B",
186
+ "70": "SCHEDULE-C",
187
+ "71": "SCHEDULE-D",
188
+ "72": "SCHEDULE-E",
189
+ "73": "SCHEDULE-F",
190
+ "74": "SCHEDULE-SE",
191
+ "75": "TAX_INSTRUCTIONS",
192
+ "76": "UNKNOWN_DOCUMENT",
193
+ "77": "VEHICLE_DONATION_ACKNOWLEDGMENT",
194
+ "78": "W-2",
195
+ "79": "W-2C",
196
+ "80": "W-2G",
197
+ "81": "W-4",
198
+ "82": "W-9",
199
+ "83": "MORTGAGE_STATEMENT",
200
+ "84": "LOAN_STATEMENT",
201
+ "85": "BROKERAGE_STATEMENT",
202
+ "86": "RETIREMENT_ACCOUNT_STATEMENT",
203
+ "87": "HSA_ACCOUNT_STATEMENT",
204
+ "88": "PAYSTUB",
205
+ "89": "INSURANCE_DOCUMENT",
206
+ "90": "CRYPTO_TAX_REPORT",
207
+ "91": "PROPERTY_TAX_BILL",
208
+ "92": "PROFIT_AND_LOSS_STATEMENT",
209
+ "93": "CONSOLIDATED_1099",
210
+ "94": "OTHER_TAX_FORM"
211
+ }
212
+ }
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "cls_token": "[CLS]",
4
+ "do_basic_tokenize": true,
5
+ "do_lower_case": true,
6
+ "is_local": true,
7
+ "local_files_only": true,
8
+ "mask_token": "[MASK]",
9
+ "max_length": 128,
10
+ "model_max_length": 512,
11
+ "never_split": null,
12
+ "pad_to_multiple_of": null,
13
+ "pad_token": "[PAD]",
14
+ "pad_token_type_id": 0,
15
+ "padding_side": "right",
16
+ "sep_token": "[SEP]",
17
+ "stride": 0,
18
+ "strip_accents": null,
19
+ "tokenize_chinese_chars": true,
20
+ "tokenizer_class": "BertTokenizer",
21
+ "truncation_side": "right",
22
+ "truncation_strategy": "longest_first",
23
+ "unk_token": "[UNK]"
24
+ }