File size: 4,437 Bytes
eff9ad8
b820014
 
 
 
69a4978
 
 
 
 
 
b820014
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1936338
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b820014
 
 
 
 
 
2fb2a34
b820014
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1936338
 
b820014
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
from fastapi import FastAPI, Request
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

from pydantic import BaseModel

app = FastAPI()

@app.get("/")
def greet_json():
    return {"Hello": "World!"}


import numpy as np
import pandas as pd

from utils import compute_features

import json

import joblib


# Define the same file path
filename = 'finalized_linear_model.joblib'

# Load the model from disk
loaded_model = joblib.load(filename)


REQUIRED_COLUMN_ORDER = [
    'num_hotel', 'num_attraction', 'num_restaurant',
    'num_convenience_store', 'num_pharmacy', 'num_cafe', 'num_bookstore',
    'num_school', 'num_co_working', 'num_clinic', 'num_bank',
    'num_supermarket', 'num_gym', 'num_fast_food', 'num_shopping_mall',
    'num_bakery', 'num_university', 'num_hospital', 'num_dentist',
    'num_clothing_store', 'num_department_store', 'num_college',
    'num_electronics_store', 'num_hostel', 'num_charging_station',
    'num_viewpoint', 'num_jewelry_store'
]

# @app.post('/predict')
# def predict_score(lat, lon):

def atm_score(num_atm, num_prediction_atm, k=7, pct=0.15):
    # num_atm = np.asarray(num_atm, dtype=float)
    # num_prediction_atm = np.asarray(num_prediction_atm, dtype=float)

    # Avoid division by zero
    eps = 1e-8
    # num_atm = num_atm*(1 + pct)
    num_prediction_atm = num_prediction_atm*(1 + pct)

    # delta = (num_atm - num_prediction_atm) / (num_prediction_atm + eps)
    delta = (num_prediction_atm - num_atm) / (num_atm + eps)

    score = 100.0 / (1.0 + np.exp(-k * (delta)))
    # score = 100 * np.exp( -k*delta ** 2 /( 300*(0.085)**2))
    return score
    
class Location(BaseModel):
    lat: float
    lon: float

@app.post("/predict")
def predict_score(location: Location, request: Request):
    lat, lon = location.lat, location.lon
    auth_header = request.headers.get("Authorization")
    
    api_key = auth_header.split(" ")[1] if auth_header else None
   
    inputs = compute_features((lat,lon), api_key, 500)
    print("[INPUTS]", inputs)
    num_banks = inputs.pop("num_banks_in_radius", 0)

    input_dict = inputs.copy()

    input_dict_new = {}

    for col in REQUIRED_COLUMN_ORDER:
        input_dict_new[col] = input_dict[col]

    mu_pred = loaded_model.predict([list(input_dict_new.values())])[0]

    # r = 1/alpha
    # p = r / (r + mu_pred)

    # # Compute pmf and mode
    # k_mode = int((r - 1) * (1 - p) / p)  # mode of NB
    # p_k = nbinom.pmf(num_banks, r, p)
    # p_mode = nbinom.pmf(k_mode, r, p)

    # # Score normalized 0–100
    # score = (p_k / p_mode) * 100
    # score = np.clip(score, 0, 100)

    # diff = (num_banks - mu_pred) / (mu_pred + 1e-6)
    # # score = (1 - np.tanh(diff))

    # print("[TANH]", np.tanh(diff))

    # diff = mu_pred2 - num_banks
    # score = 100 / (1 + np.exp(-alpha * diff))

    # score = np.abs(1 + np.tanh(diff)) / 2 * 100


    # score = (1 * np.abs(mu_pred2 + 0.1)) * 100

    # score = np.sigmoid(mu_pred2 - num_banks + 0.1) * 100

    # score =  100 / (1 + np.exp(num_banks - mu_pred))
    score = atm_score(num_banks, mu_pred)

    input_dict_new.update({
        "score":round(float(score), 3),
        "num_atm":num_banks,
        "num_prediction_atm":round(float(mu_pred), 3),
        "lat":lat,
        "lon":lon
    })

    return input_dict_new

    # return (
    #     round(float(score), 3),
    #     num_banks,
    #     round(float(mu_pred), 3),
    #     # round(float(log_score),3)
    #     # "Normal Score": round(float(normal_score), 3),
    #     # input_dict["total_amenities"],

    #     *[v for k,v in input_dict_new.items() if k[:3] == "num"]

    # )

# # ======== Gradio Interface ========
# interface = gr.Interface(
#     fn=predict_score,
#     inputs=[
#         gr.Number(label="Latitude"),
#         gr.Number(label="Longitude"),
#         gr.Text(label="Google Api Key")
#     ],
#     outputs=[
#         gr.Number(label="Score (0 - 100)"),
#         gr.Number(label="Current ATMs"),
#         gr.Number(label="Ideal ATMs"),
#         # gr.Number(label="Log Score Probability"),

#         # gr.Number(label="Total Amenities"),

#         *[gr.Number(label=x) for x in REQUIRED_COLUMN_ORDER]
#     ],
#     title="Bank Location Scoring Model",
#     description="Enter latitude and longitude to get the predicted score, number of banks, and normalized score.",
# )


# interface.launch()