MrUtakata commited on
Commit
015c6bc
Β·
verified Β·
1 Parent(s): 25d2c15

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -32
app.py CHANGED
@@ -2,7 +2,7 @@
2
 
3
  import streamlit as st
4
 
5
- # ─── THIS MUST BE FIRST ───────────────────────────────────────────────────────
6
  st.set_page_config(page_title="Keystroke Dynamics Auth", layout="wide")
7
 
8
  import pandas as pd
@@ -10,7 +10,7 @@ import numpy as np
10
  import joblib
11
  import tensorflow as tf
12
 
13
- # ─── Caching loaders so they only run only once per session ──────────────────
14
  @st.cache_resource
15
  def load_preprocessor(path="preprocessor.pkl"):
16
  return joblib.load(path)
@@ -23,63 +23,69 @@ def load_label_encoder(path="label_encoder.pkl"):
23
  def load_model(path="keystroke_dnn.h5"):
24
  return tf.keras.models.load_model(path)
25
 
26
- # ─── Prediction function ────────────────────────────────────────────────────
27
  def predict_subjects(df_raw):
28
  preprocessor = load_preprocessor()
29
  label_encoder = load_label_encoder()
30
  model = load_model()
31
 
32
- # 1) Drop unused cols if present
33
  for c in ("subject", "sessionIndex", "rep"):
34
  if c in df_raw.columns:
35
  df_raw = df_raw.drop(columns=[c])
36
 
37
- # 2) Re-order columns exactly as during training
38
  feature_cols = preprocessor.transformers_[0][2]
39
  df_features = df_raw[feature_cols]
40
 
41
- # 3) Scale
42
  X_scaled = preprocessor.transform(df_features)
43
-
44
- # 4) Model inference
45
  y_prob = model.predict(X_scaled)
46
  idx_pred = np.argmax(y_prob, axis=1)
47
-
48
- # 5) Decode one‐hot back to original labels
49
  labels = label_encoder.categories_[0][idx_pred]
50
 
51
- # 6) Build output
52
  df_out = pd.DataFrame({"predicted_subject": labels})
53
  for i, cls in enumerate(label_encoder.categories_[0]):
54
  df_out[f"prob_{cls}"] = y_prob[:, i]
55
-
56
  return df_out
57
 
58
- # ─── Streamlit UI ──────────────────────────────────────────────────────────
59
  def main():
60
  st.title("πŸ”‘ Keystroke Dynamics Authentication")
61
  st.markdown(
62
- "Upload a CSV of raw keystroke‐feature vectors (one row per sample). "
63
- "The app will drop any `subject`/`sessionIndex`/`rep` columns, scale, "
64
- "run through the DNN, and return predicted subject IDs + confidence scores."
65
  )
66
 
67
- uploaded = st.file_uploader("Choose CSV file", type="csv")
68
- if not uploaded:
69
- return
70
-
71
- df = pd.read_csv(uploaded)
72
- st.write("### Raw feature preview (first 5 rows)")
73
- st.dataframe(df.head(), use_container_width=True)
74
-
75
- try:
76
- df_preds = predict_subjects(df)
77
- st.write("### Predictions")
78
- st.dataframe(df_preds, use_container_width=True)
79
- except KeyError as e:
80
- st.error(f"Missing expected feature column: {e}")
81
- except Exception as e:
82
- st.error(f"Error during prediction: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
  if __name__ == "__main__":
85
  main()
 
2
 
3
  import streamlit as st
4
 
5
+ # ─── MUST BE FIRST ───────────────────────────────────────────────────────────
6
  st.set_page_config(page_title="Keystroke Dynamics Auth", layout="wide")
7
 
8
  import pandas as pd
 
10
  import joblib
11
  import tensorflow as tf
12
 
13
+ # ─── Caching loaders so they only run once per session ───────────────────────
14
  @st.cache_resource
15
  def load_preprocessor(path="preprocessor.pkl"):
16
  return joblib.load(path)
 
23
  def load_model(path="keystroke_dnn.h5"):
24
  return tf.keras.models.load_model(path)
25
 
26
+ # ─── Prediction helper ───────────────────────────────────────────────────────
27
  def predict_subjects(df_raw):
28
  preprocessor = load_preprocessor()
29
  label_encoder = load_label_encoder()
30
  model = load_model()
31
 
32
+ # Drop any stray columns
33
  for c in ("subject", "sessionIndex", "rep"):
34
  if c in df_raw.columns:
35
  df_raw = df_raw.drop(columns=[c])
36
 
37
+ # Re-order to exact feature list
38
  feature_cols = preprocessor.transformers_[0][2]
39
  df_features = df_raw[feature_cols]
40
 
41
+ # Scale, predict, decode
42
  X_scaled = preprocessor.transform(df_features)
 
 
43
  y_prob = model.predict(X_scaled)
44
  idx_pred = np.argmax(y_prob, axis=1)
 
 
45
  labels = label_encoder.categories_[0][idx_pred]
46
 
47
+ # Build output table
48
  df_out = pd.DataFrame({"predicted_subject": labels})
49
  for i, cls in enumerate(label_encoder.categories_[0]):
50
  df_out[f"prob_{cls}"] = y_prob[:, i]
 
51
  return df_out
52
 
53
+ # ─── Streamlit App ──────────────────────────────────────────────────────────
54
  def main():
55
  st.title("πŸ”‘ Keystroke Dynamics Authentication")
56
  st.markdown(
57
+ "Use the sidebar to enter one row of raw keystroke features, then click **Predict**. "
58
+ "The model will return the predicted subject ID plus per-class probabilities."
 
59
  )
60
 
61
+ # Load the feature‐list so we can build inputs
62
+ preprocessor = load_preprocessor()
63
+ feature_cols = preprocessor.transformers_[0][2]
64
+
65
+ st.sidebar.header("Enter keystroke features")
66
+ user_vals = {}
67
+ # one number_input per feature
68
+ for col in feature_cols:
69
+ # you can tweak min/max/default as appropriate
70
+ user_vals[col] = st.sidebar.number_input(col, value=0.0, format="%.4f")
71
+
72
+ if st.sidebar.button("Predict"):
73
+ # pack into single-row DataFrame
74
+ df_input = pd.DataFrame([user_vals], columns=feature_cols)
75
+
76
+ # Show what we're about to send
77
+ st.write("### Your input")
78
+ st.dataframe(df_input, use_container_width=True)
79
+
80
+ # Do prediction
81
+ try:
82
+ df_pred = predict_subjects(df_input)
83
+ st.write("### Prediction")
84
+ st.dataframe(df_pred, use_container_width=True)
85
+ except KeyError as e:
86
+ st.error(f"Missing feature (typo?): {e}")
87
+ except Exception as e:
88
+ st.error(f"Prediction error: {e}")
89
 
90
  if __name__ == "__main__":
91
  main()