Views
No views yet
| Average Type | Precision | Recall | F1-Score |
|---|---|---|---|
| Micro Average | 0.93 | 0.94 | 0.94 |
| Macro Average | 0.80 | 0.80 | 0.80 |
| Weighted Average | 0.93 | 0.94 | 0.94 |
1import torch
2from transformers import AutoTokenizer, AutoModelForTokenClassification
3import warnings
4warnings.filterwarnings("ignore")
5
6class IndianAddressNER:
7 def __init__(self):
8 model_name = "shiprocket-ai/open-tinybert-indian-address-ner"
9 self.tokenizer = AutoTokenizer.from_pretrained(model_name)
10 self.model = AutoModelForTokenClassification.from_pretrained(model_name)
11 self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
12 self.model.to(self.device)
13 self.model.eval()
14
15 # Entity mappings
16 self.id2entity = {
17 "0": "O",
18 "1": "B-building_name",
19 "2": "I-building_name",
20 "3": "B-city",
21 "4": "I-city",
22 "5": "B-country",
23 "6": "I-country",
24 "7": "B-floor",
25 "8": "I-floor",
26 "9": "B-house_details",
27 "10": "I-house_details",
28 "11": "B-locality",
29 "12": "I-locality",
30 "13": "B-pincode",
31 "14": "I-pincode",
32 "15": "B-road",
33 "16": "I-road",
34 "17": "B-state",
35 "18": "I-state",
36 "19": "B-sub_locality",
37 "20": "I-sub_locality",
38 "21": "B-landmarks",
39 "22": "I-landmarks"
40}
41
42 def predict(self, address):
43 """Extract entities from an Indian address - FIXED VERSION"""
44 if not address.strip():
45 return {}
46
47 # Tokenize with offset mapping for better text reconstruction
48 inputs = self.tokenizer(
49 address,
50 return_tensors="pt",
51 truncation=True,
52 padding=True,
53 max_length=128,
54 return_offsets_mapping=True
55 )
56
57 # Extract offset mapping before moving to device
58 offset_mapping = inputs.pop("offset_mapping")[0]
59 inputs = {k: v.to(self.device) for k, v in inputs.items()}
60
61 # Predict
62 with torch.no_grad():
63 outputs = self.model(**inputs)
64 predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
65 predicted_ids = torch.argmax(predictions, dim=-1)
66 confidence_scores = torch.max(predictions, dim=-1)[0]
67
68 # Extract entities using offset mapping
69 entities = self.extract_entities_with_offsets(
70 address,
71 predicted_ids[0],
72 confidence_scores[0],
73 offset_mapping
74 )
75
76 return entities
77
78 def extract_entities_with_offsets(self, original_text, predicted_ids, confidences, offset_mapping):
79 """Extract entities using offset mapping for accurate text reconstruction"""
80 entities = {}
81 current_entity = None
82
83 for i, (pred_id, conf) in enumerate(zip(predicted_ids, confidences)):
84 if i >= len(offset_mapping):
85 break
86
87 start, end = offset_mapping[i]
88
89 # Skip special tokens (they have (0,0) mapping)
90 if start == end == 0:
91 continue
92
93 label = self.id2entity.get(str(pred_id.item()), "O")
94
95 if label.startswith("B-"):
96 # Save previous entity
97 if current_entity:
98 entity_type = current_entity["type"]
99 if entity_type not in entities:
100 entities[entity_type] = []
101 entities[entity_type].append({
102 "text": current_entity["text"],
103 "confidence": current_entity["confidence"]
104 })
105
106 # Start new entity
107 entity_type = label[2:] # Remove "B-"
108 current_entity = {
109 "type": entity_type,
110 "text": original_text[start:end],
111 "confidence": conf.item(),
112 "start": start,
113 "end": end
114 }
115
116 elif label.startswith("I-") and current_entity:
117 # Continue current entity
118 entity_type = label[2:] # Remove "I-"
119 if entity_type == current_entity["type"]:
120 # Extend the entity to include this token
121 current_entity["text"] = original_text[current_entity["start"]:end]
122 current_entity["confidence"] = (current_entity["confidence"] + conf.item()) / 2
123 current_entity["end"] = end
124
125 elif label == "O" and current_entity:
126 # End current entity
127 entity_type = current_entity["type"]
128 if entity_type not in entities:
129 entities[entity_type] = []
130 entities[entity_type].append({
131 "text": current_entity["text"],
132 "confidence": current_entity["confidence"]
133 })
134 current_entity = None
135
136 # Add final entity if exists
137 if current_entity:
138 entity_type = current_entity["type"]
139 if entity_type not in entities:
140 entities[entity_type] = []
141 entities[entity_type].append({
142 "text": current_entity["text"],
143 "confidence": current_entity["confidence"]
144 })
145
146 return entities
147
148# Usage example
149ner = IndianAddressNER()
150
151# Test addresses
152test_addresses = [
153 "Shop No 123, Sunshine Apartments, Andheri West, Mumbai, 400058",
154 "DLF Cyber City, Sector 25, Gurgaon, Haryana",
155 "Flat 201, MG Road, Bangalore, Karnataka, 560001",
156 "Phoenix Mall, Kurla West, Mumbai"
157]
158
159print("🏠 INDIAN ADDRESS NER EXAMPLES")
160print("=" * 50)
161
162for address in test_addresses:
163 print(f"\n📍 Address: {address}")
164 entities = ner.predict(address)
165
166 if entities:
167 for entity_type, entity_list in sorted(entities.items()):
168 print(f"🏷️ {entity_type.replace('_', ' ').title()}:")
169 for entity in entity_list:
170 confidence = entity['confidence']
171 text = entity['text']
172 confidence_icon = "🟢" if confidence > 0.8 else "🟡" if confidence > 0.6 else "🔴"
173 print(f" {confidence_icon} {text} (confidence: {confidence:.3f})")
174 else:
175 print("❌ No entities found")
176 print("-" * 40)1{
2 "entity2id": {
3 "O": 0,
4 "B-building_name": 1,
5 "I-building_name": 2,
6 "B-city": 3,
7 "I-city": 4,
8 "B-country": 5,
9 "I-country": 6,
10 "B-floor": 7,
11 "I-floor": 8,
12 "B-house_details": 9,
13 "I-house_details": 10,
14 "B-locality": 11,
15 "I-locality": 12,
16 "B-pincode": 13,
17 "I-pincode": 14,
18 "B-road": 15,
19 "I-road": 16,
20 "B-state": 17,
21 "I-state": 18,
22 "B-sub_locality": 19,
23 "I-sub_locality": 20,
24 "B-landmarks": 21,
25 "I-landmarks": 22
26 },
27 "id2entity": {
28 "0": "O",
29 "1": "B-building_name",
30 "2": "I-building_name",
31 "3": "B-city",
32 "4": "I-city",
33 "5": "B-country",
34 "6": "I-country",
35 "7": "B-floor",
36 "8": "I-floor",
37 "9": "B-house_details",
38 "10": "I-house_details",
39 "11": "B-locality",
40 "12": "I-locality",
41 "13": "B-pincode",
42 "14": "I-pincode",
43 "15": "B-road",
44 "16": "I-road",
45 "17": "B-state",
46 "18": "I-state",
47 "19": "B-sub_locality",
48 "20": "I-sub_locality",
49 "21": "B-landmarks",
50 "22": "I-landmarks"
51 }
52}config.json: Model configuration and hyperparameterspytorch_model.bin / model.safetensors: Model weightstokenizer.json: Tokenizer configurationtokenizer_config.json: Tokenizer settingsvocab.txt: Vocabulary fileentity_mappings.json: Entity type mappings1@misc{open-tinybert-indian-address-ner,
2 title={TinyBERT Indian Address NER Model},
3 year={2025},
4 publisher={Hugging Face},
5 url={https://huggingface.co/shiprocket-ai/open-tinybert-indian-address-ner}
6}