├── file2 ├── file6 ├── file5 ├── file7 ├── README.md └── File1 /file2: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from tensorflow.keras.models import Sequential 3 | from tensorflow.keras.layers import LSTM, Dense 4 | 5 | # Simulate time-series stakeholder data: (samples, timesteps, features) 6 | num_stakeholders = 100 7 | timesteps = 10 # e.g., 10 weeks 8 | features = 4 # comm_freq, attendance, feedback_quality, responsiveness 9 | 10 | X = np.random.rand(num_stakeholders, timesteps, features) 11 | y = np.random.randint(0, 3, size=num_stakeholders) # 0=Low, 1=Medium, 2=High 12 | 13 | # LSTM Model 14 | model = Sequential([ 15 | LSTM(64, input_shape=(timesteps, features)), 16 | Dense(32, activation='relu'), 17 | Dense(3, activation='softmax') 18 | ]) 19 | model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) 20 | model.fit(X, y, epochs=20, batch_size=8) 21 | -------------------------------------------------------------------------------- /file6: -------------------------------------------------------------------------------- 1 | # streamlit_app.py 2 | import streamlit as st 3 | import pandas as pd 4 | import joblib 5 | from utils.risk_mapping import map_risk_level 6 | 7 | st.set_page_config(page_title="Stakeholder Engagement Detection", layout="centered") 8 | st.title("🔍 Stakeholder Engagement Level Detection Dashboard") 9 | 10 | # Load model 11 | model = joblib.load("models/rf_model.pkl") 12 | 13 | # Upload CSV 14 | uploaded_file = st.file_uploader("Upload stakeholder data (CSV)", type=["csv"]) 15 | 16 | if uploaded_file is not None: 17 | df = pd.read_csv(uploaded_file) 18 | st.subheader("📋 Uploaded Data Preview") 19 | st.dataframe(df) 20 | 21 | try: 22 | # Make predictions 23 | predictions = model.predict(df) 24 | mapping = {0: "Low", 1: "Medium", 2: "High"} 25 | df["Engagement Level"] = [mapping[p] for p in predictions] 26 | 27 | # Map to risk 28 | df["Risk Score"] = df["Engagement Level"].apply(map_risk_level) 29 | 30 | st.subheader("📊 Prediction & Risk Mapping") 31 | st.dataframe(df) 32 | 33 | st.success("Prediction complete. Analyze the risk scores below.") 34 | except Exception as e: 35 | st.error(f"Error in prediction: {e}") 36 | -------------------------------------------------------------------------------- /file5: -------------------------------------------------------------------------------- 1 | # train_rf_model.py 2 | import pandas as pd 3 | import numpy as np 4 | import joblib 5 | from sklearn.ensemble import RandomForestClassifier 6 | from sklearn.model_selection import train_test_split 7 | from sklearn.metrics import classification_report 8 | 9 | # Generate synthetic data 10 | np.random.seed(42) 11 | samples = 500 12 | 13 | data = pd.DataFrame({ 14 | "communication_freq": np.random.randint(0, 11, samples), 15 | "meeting_attendance": np.random.randint(50, 101, samples), 16 | "feedback_quality": np.random.randint(1, 6, samples), 17 | "responsiveness": np.random.randint(1, 6, samples) 18 | }) 19 | 20 | def label_engagement(row): 21 | score = (row["communication_freq"] * 0.3 + 22 | row["meeting_attendance"] * 0.2 + 23 | row["feedback_quality"] * 0.25 + 24 | row["responsiveness"] * 0.25) 25 | if score < 30: 26 | return 0 # Low 27 | elif score < 60: 28 | return 1 # Medium 29 | else: 30 | return 2 # High 31 | 32 | # Apply label 33 | data["engagement_level"] = data.apply(label_engagement, axis=1) 34 | 35 | # Train/test split 36 | X = data.drop(columns=["engagement_level"]) 37 | y = data["engagement_level"] 38 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) 39 | 40 | # Train RandomForest 41 | model = RandomForestClassifier(n_estimators=100, random_state=42) 42 | model.fit(X_train, y_train) 43 | 44 | # Save model 45 | joblib.dump(model, "models/rf_model.pkl") 46 | 47 | # Evaluation 48 | pred = model.predict(X_test) 49 | print(classification_report(y_test, pred, target_names=["Low", "Medium", "High"])) 50 | -------------------------------------------------------------------------------- /file7: -------------------------------------------------------------------------------- 1 | # streamlit_app.py 2 | import streamlit as st 3 | import pandas as pd 4 | import joblib 5 | import os 6 | 7 | # Define simple risk mapping function 8 | RISK_MAP = { 9 | "Low": 0.8, # High risk 10 | "Medium": 0.5, # Moderate risk 11 | "High": 0.2 # Low risk 12 | } 13 | 14 | def map_risk_level(level): 15 | return RISK_MAP.get(level, 0.5) 16 | 17 | # Streamlit UI 18 | st.set_page_config(page_title="Stakeholder Engagement Detection", layout="centered") 19 | st.title("🔍 Stakeholder Engagement Level Detection Dashboard") 20 | 21 | # Load model 22 | model_path = "models/rf_model.pkl" 23 | if not os.path.exists(model_path): 24 | st.error("Model file not found. Please train the model using train_rf_model.py.") 25 | else: 26 | model = joblib.load(model_path) 27 | 28 | # Upload CSV 29 | uploaded_file = st.file_uploader("Upload stakeholder data (CSV)", type=["csv"]) 30 | 31 | if uploaded_file is not None: 32 | df = pd.read_csv(uploaded_file) 33 | st.subheader("📋 Uploaded Data Preview") 34 | st.dataframe(df) 35 | 36 | try: 37 | # Make predictions 38 | predictions = model.predict(df) 39 | mapping = {0: "Low", 1: "Medium", 2: "High"} 40 | df["Engagement Level"] = [mapping[p] for p in predictions] 41 | 42 | # Map to risk 43 | df["Risk Score"] = df["Engagement Level"].apply(map_risk_level) 44 | 45 | st.subheader("📊 Prediction & Risk Mapping") 46 | st.dataframe(df) 47 | 48 | st.success("Prediction complete. Analyze the risk scores below.") 49 | except Exception as e: 50 | st.error(f"Error in prediction: {e}") 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # README.md 2 | 3 | ## 📊 Stakeholder Engagement Level Detection 4 | 5 | This project provides a machine learning-powered solution to assess stakeholder engagement levels and their corresponding risk levels using synthetic data. The app is designed for project managers, sustainability analysts, and data scientists interested in stakeholder dynamics and project risk management. 6 | 7 | --- 8 | 9 | ### 🔧 Components 10 | 11 | - **`train_rf_model.py`** – Generates synthetic data and trains a Random Forest classifier. 12 | - **`streamlit_app.py`** – Streamlit dashboard for interactive prediction. 13 | - **Risk Mapping Function** – Maps predicted engagement levels (Low, Medium, High) to risk scores. 14 | 15 | --- 16 | 17 | ### 🗂️ File Structure 18 | ``` 19 | stakeholder_engagement/ 20 | │ 21 | ├── models/ 22 | │ └── rf_model.pkl # Trained RF model 23 | │ 24 | ├── app/ 25 | │ └── streamlit_app.py # Main dashboard 26 | │ 27 | ├── data/ 28 | │ └── sample_stakeholders.csv # Example stakeholder input 29 | │ 30 | ├── train_rf_model.py # Model training script 31 | ├── README.md # This file 32 | ``` 33 | 34 | --- 35 | 36 | ### 🚀 How to Use 37 | 1. **Install dependencies** 38 | ```bash 39 | pip install pandas scikit-learn streamlit joblib 40 | ``` 41 | 42 | 2. **Train the model** 43 | ```bash 44 | python train_rf_model.py 45 | ``` 46 | 47 | 3. **Run the dashboard** 48 | ```bash 49 | streamlit run app/streamlit_app.py 50 | ``` 51 | 52 | 4. **Upload stakeholder CSV** with the following format: 53 | ```csv 54 | communication_freq,meeting_attendance,feedback_quality,responsiveness 55 | 5,80,4,5 56 | 3,60,2,2 57 | ... 58 | ``` 59 | 60 | --- 61 | 62 | ### 📈 Engagement Levels & Risk Scores 63 | | Engagement Level | Risk Score | Description | 64 | |------------------|------------|----------------------| 65 | | High | 0.2 | Low risk, proactive | 66 | | Medium | 0.5 | Moderate risk | 67 | | Low | 0.8 | High risk, inactive | 68 | 69 | --- 70 | 71 | ### 📌 To-Do (Next Phase) 72 | - [ ] Add LSTM model for temporal tracking. 73 | - [ ] Deploy as a web app (e.g., Streamlit Cloud). 74 | - [ ] Add CSV export of results. 75 | 76 | --- 77 | 78 | ### 👨‍💻 Author 79 | Developed by [Geosoft Global Innovation Ltd.](https://github.com/Akajiaku1) | Powered by synthetic ML and stakeholder science. 80 | -------------------------------------------------------------------------------- /File1: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from sklearn.model_selection import train_test_split 4 | from sklearn.ensemble import RandomForestClassifier 5 | from sklearn.metrics import classification_report, confusion_matrix 6 | import matplotlib.pyplot as plt 7 | import seaborn as sns 8 | 9 | # Step 1: Generate Synthetic Data 10 | np.random.seed(42) 11 | num_samples = 500 12 | 13 | data = pd.DataFrame({ 14 | "communication_freq": np.random.randint(0, 11, size=num_samples), # 0–10 per month 15 | "meeting_attendance": np.random.randint(0, 101, size=num_samples), # percentage 16 | "feedback_quality": np.random.randint(1, 6, size=num_samples), # 1–5 scale 17 | "responsiveness": np.random.randint(1, 6, size=num_samples), # 1–5 scale 18 | }) 19 | 20 | # Step 2: Define Engagement Level 21 | def engagement_level(row): 22 | score = ( 23 | row["communication_freq"] * 0.3 + 24 | row["meeting_attendance"] * 0.2 + 25 | row["feedback_quality"] * 0.25 + 26 | row["responsiveness"] * 0.25 27 | ) 28 | if score < 30: 29 | return "Low" 30 | elif 30 <= score < 60: 31 | return "Medium" 32 | else: 33 | return "High" 34 | 35 | data["engagement_level"] = data.apply(engagement_level, axis=1) 36 | 37 | # Step 3: Encode Target Variable 38 | target_map = {"Low": 0, "Medium": 1, "High": 2} 39 | data["target"] = data["engagement_level"].map(target_map) 40 | 41 | # Step 4: Train-Test Split 42 | X = data.drop(columns=["engagement_level", "target"]) 43 | y = data["target"] 44 | 45 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) 46 | 47 | # Step 5: Model Training 48 | model = RandomForestClassifier(n_estimators=100, random_state=42) 49 | model.fit(X_train, y_train) 50 | 51 | # Step 6: Evaluation 52 | y_pred = model.predict(X_test) 53 | 54 | print("Classification Report:") 55 | print(classification_report(y_test, y_pred, target_names=["Low", "Medium", "High"])) 56 | 57 | print("Confusion Matrix:") 58 | cm = confusion_matrix(y_test, y_pred) 59 | sns.heatmap(cm, annot=True, fmt="d", cmap="Blues", xticklabels=["Low", "Medium", "High"], yticklabels=["Low", "Medium", "High"]) 60 | plt.xlabel("Predicted") 61 | plt.ylabel("True") 62 | plt.title("Confusion Matrix") 63 | plt.show() 64 | 65 | # Optional: Predict New Stakeholder Example 66 | new_stakeholder = pd.DataFrame({ 67 | "communication_freq": [7], 68 | "meeting_attendance": [85], 69 | "feedback_quality": [4], 70 | "responsiveness": [5] 71 | }) 72 | predicted_level = model.predict(new_stakeholder)[0] 73 | print("Predicted Engagement Level:", list(target_map.keys())[list(target_map.values()).index(predicted_level)]) 74 | --------------------------------------------------------------------------------