Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/ai/hourly predictions #370

Merged
merged 10 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions frontend/occupi-mobile4/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@
"lint": "expo lint"
},
"jest": {
"preset": "jest-expo",
"transformIgnorePatterns": [
"node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg|@gluestack-ui/themed|expo-device)"
],
"collectCoverage": true,
"coverageReporters": ["lcov", "text"],
"coverageDirectory": "coverage",
"setupFiles": [
"./node_modules/react-native-gesture-handler/jestSetup.js",
"./jest.setup.js"
]
},
"preset": "jest-expo",
"transformIgnorePatterns": [
"node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg|@gluestack-ui/themed|expo-device)"
],
"collectCoverage": true,
"coverageReporters": [
"lcov",
"text"
],
"coverageDirectory": "coverage",
"setupFiles": [
"./node_modules/react-native-gesture-handler/jestSetup.js",
"./jest.setup.js"
]
},
"dependencies": {
"@eva-design/eva": "^2.2.0",
"@expo/vector-icons": "^14.0.0",
Expand All @@ -45,19 +48,23 @@
"@ui-kitten/components": "^5.3.1",
"axios": "^1.7.2",
"date-fns": "^3.6.0",
"expo": "~51.0.14",
"expo": "^51.0.32",
"expo-blur": "^13.0.2",
"expo-checkbox": "~3.0.0",
"expo-constants": "~16.0.2",
"expo-device": "~6.0.2",
"expo-file-system": "^17.0.1",
"expo-font": "~12.0.7",
"expo-haptics": "~13.0.1",
"expo-linear-gradient": "~13.0.2",
"expo-linking": "~6.3.1",
"expo-local-authentication": "^14.0.1",
"expo-location": "~17.0.1",
"expo-notifications": "~0.28.9",
"expo-print": "~13.0.1",
"expo-router": "~3.5.16",
"expo-secure-store": "~13.0.2",
"expo-sensors": "~13.0.9",
"expo-sharing": "~12.0.1",
"expo-splash-screen": "~0.27.5",
"expo-status-bar": "~1.12.1",
Expand Down Expand Up @@ -89,11 +96,7 @@
"react-native-web": "~0.19.10",
"reanimated-color-picker": "^3.0.4",
"tinycolor2": "^1.6.0",
"zod": "^3.23.8",
"expo-location": "~17.0.1",
"expo-sensors": "~13.0.9",
"expo-haptics": "~13.0.1",
"expo-checkbox": "~3.0.0"
"zod": "^3.23.8"
},
"devDependencies": {
"@babel/core": "^7.25.2",
Expand Down
1 change: 0 additions & 1 deletion frontend/occupi-mobile4/screens/Dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ const Dashboard: React.FC = () => {
setCurrentData(weeklyData);
}


const useLocationCheckin = () => {
Alert.alert(
'At the office',
Expand Down
11,949 changes: 11,949 additions & 0 deletions frontend/occupi-mobile4/yarn.lock

Large diffs are not rendered by default.

151 changes: 151 additions & 0 deletions maestro/Hourly.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, StandardScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Flatten, Dense, Dropout, LSTM
from tensorflow import keras
import numpy as np
import joblib

# Load the Excel file
file_path = 'datasets/Hourly_Predictions.xlsx' # Replace with your actual file path
excel_data = pd.ExcelFile(file_path)

# Combine all sheets into one DataFrame
sheets_data = {sheet: excel_data.parse(sheet) for sheet in excel_data.sheet_names}
combined_data = pd.concat(sheets_data.values(), keys=sheets_data.keys(), names=['Day', 'Index']).reset_index(level=1, drop=True).reset_index()

# Data Preparation
label_encoder_day = LabelEncoder()
combined_data['Day_Encoded'] = label_encoder_day.fit_transform(combined_data['Day'].fillna('Unknown'))

# Extract hour from 'Time' column
combined_data['Hour'] = combined_data['Time'].apply(lambda t: t.hour if pd.notnull(t) else 0)

# Define bins and labels for each day (customized for each day of the week)
day_bins = {
'Monday': [0, 50, 100, 150, 200, 250, 300, float('inf')],
'Tuesday': [0, 300, 600, 900, 1200, 1500, 1800, float('inf')],
'Wednesday': [0, 50, 100, 150, 200, 250, 300, float('inf')],
'Thursday': [0, 300, 600, 900, 1200, 1500, 1800, float('inf')],
'Friday': [0, 50, 100, 150, 200, 250, 300, float('inf')],
'Saturday': [0, 25, 50, 75, 100, 125, 150, float('inf')],
'Sunday': [0, 10, 20, 30, 40, 50, 60, float('inf')],
}

day_labels = {
'Monday': list(range(len(day_bins['Monday']) - 1)),
'Tuesday': list(range(len(day_bins['Tuesday']) - 1)),
'Wednesday': list(range(len(day_bins['Wednesday']) - 1)),
'Thursday': list(range(len(day_bins['Thursday']) - 1)),
'Friday': list(range(len(day_bins['Friday']) - 1)),
'Saturday': list(range(len(day_bins['Saturday']) - 1)),
'Sunday': list(range(len(day_bins['Sunday']) - 1)),
}

# Function to apply appropriate bins for each day
def apply_bins(row):
day = row['Day']
bins = day_bins.get(day, [0, float('inf')]) # Default if not found
labels = day_labels.get(day, [0])
return pd.cut([row['Attendance']], bins=bins, labels=labels, include_lowest=True)[0]

combined_data['Attendance_Bin'] = combined_data.apply(apply_bins, axis=1)

# Drop missing bins and convert to integers
combined_data.dropna(subset=['Attendance_Bin'], inplace=True)
combined_data['Attendance_Bin'] = combined_data['Attendance_Bin'].astype(int)

# Encode attendance bins
y = combined_data['Attendance_Bin']

# Standardize the 'Hour' feature
scaler = StandardScaler()
hour_scaled = scaler.fit_transform(combined_data['Hour'].values.reshape(-1, 1))
joblib.dump(scaler, 'hourly_scaler.pkl')

# Prepare features
X_scaled = np.hstack([combined_data['Day_Encoded'].values.reshape(-1, 1), hour_scaled])

# Reshape for CNN input
X_scaled = X_scaled.reshape(X_scaled.shape[0], X_scaled.shape[1], 1)

# Convert labels to categorical
y_categorical = keras.utils.to_categorical(y)
num_classes = y_categorical.shape[1]

# Train-test split
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y_categorical, test_size=0.2, random_state=42)

# Define CNN + LSTM model
model = keras.Sequential([
keras.layers.Conv1D(input_shape=(X_train.shape[1], 1), filters=64, kernel_size=1, activation='relu', name='Conv1D'),
keras.layers.MaxPooling1D(pool_size=1, name='MaxPool1D'),
keras.layers.LSTM(50, return_sequences=False, name='LSTM'),
keras.layers.Flatten(name='Flatten'),
keras.layers.Dense(50, activation='relu', name='Dense_1'),
keras.layers.Dropout(0.5, name='Dropout'),
keras.layers.Dense(num_classes, activation='softmax', name='Output')
])

# Print the model summary
model.summary()

# Compile the model
model.compile(optimizer='adam',
loss=keras.losses.CategoricalCrossentropy(from_logits=False), # From logits is False since output is softmax
metrics=[keras.metrics.CategoricalAccuracy()])

# Define training parameters
epochs = 30
batch_size = 16
testing = False

# Train the model
model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, validation_split=0.2)

# Evaluate the model
test_loss, test_acc = model.evaluate(X_test, y_test)
print('\nTest accuracy: {}'.format(test_acc))

# Save the model
# model.export('python-code/models/hourly_predictions/1')

def predict_for_day_hour(model, day, hour, label_encoder, scaler):
"""
Predict attendance for a specific day and hour.

Parameters:
model: Trained Keras model used for predictions.
day: String representing the day of the week (e.g., 'Monday').
hour: Integer representing the hour of the day (0-23).
label_encoder: LabelEncoder instance used to encode day labels during training.
scaler: StandardScaler instance used to scale hour feature during training.

Returns:
predicted_bin: Predicted attendance bin for the input day and hour.
"""
# Encode the day using the label encoder (same as training)
day_encoded = label_encoder.transform([day])[0]

# Scale the hour using the same scaler as in training
hour_scaled = scaler.transform(np.array([[hour]]))

# Prepare the input (reshape to match model's input shape)
input_data = np.array([[day_encoded, hour_scaled[0][0]]]).reshape(1, 2, 1)

# Predict the attendance bin (returns a probability for each class)
prediction = model.predict(input_data)
print(prediction)

# Convert the prediction from probabilities to class (attendance bin)
predicted_bin = np.argmax(prediction, axis=1)[0]

return predicted_bin

# Example usage
day_input = 'Monday'
hour_input = 10 # 10 AM
predicted_bin = predict_for_day_hour(model, day_input, hour_input, label_encoder_day, scaler)
print(f"Predicted attendance bin for {day_input} at {hour_input}:00 is {predicted_bin}")

51 changes: 51 additions & 0 deletions maestro/warmup_data(2).py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# import tensorflow as tf
# import numpy as np
# import os
# from tensorflow_serving.apis import predict_pb2, prediction_log_pb2

# # Function to create representative input data
# def create_warmup_data(input_shape):
# # Generate random data with the given input shape
# example_input = np.random.rand(*input_shape).astype(np.float32)
# return example_input

# # Save the warmup data as a TFRecord in a format compatible with TensorFlow Serving
# def save_warmup_data(file_path, warmup_data):
# # Create the PredictRequest for TensorFlow Serving
# warmup_request = predict_pb2.PredictRequest()
# warmup_request.model_spec.name = 'hourly_model' # Replace with your model name
# warmup_request.model_spec.signature_name = 'serving_default'

# # Fill in the input data - ensure that 'input_data' matches your model's input signature name
# warmup_request.inputs['input_data'].CopyFrom(
# tf.make_tensor_proto(warmup_data, dtype=tf.float32)
# )

# # Create a PredictionLog containing the request
# warmup_log = prediction_log_pb2.PredictionLog(
# predict_log=prediction_log_pb2.PredictLog(request=warmup_request)
# )

# # Write to the TFRecord file
# with tf.io.TFRecordWriter(file_path) as writer:
# writer.write(warmup_log.SerializeToString())

# # Model's input shape (batch size is None, so replace it with 1)
# input_shape = (1, 2, 1) # Replace with your model's input shape without the batch size

# # Generate warmup data
# warmup_data = create_warmup_data(input_shape)

# # Define the file path for the warmup file
# warmup_file_path = 'C:/Users/retha/Capstone/occupi/models/hourly_predictions/1/assets.extra/tf_serving_warmup_requests'

# # Create the necessary directory if it doesn't exist
# os.makedirs(os.path.dirname(warmup_file_path), exist_ok=True)

# # Save the warmup data in TensorFlow Serving format
# save_warmup_data(warmup_file_path, warmup_data)

# print(f"Warm-up request saved to {warmup_file_path}")

import tensorflow as tf
print(tf.__version__)
Binary file modified python-code/__pycache__/prediction.cpython-312.pyc
Binary file not shown.
Loading
Loading