import gradio as gr import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import io from sklearn.preprocessing import MinMaxScaler from statsmodels.tsa.arima.model import ARIMA from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout import warnings warnings.filterwarnings("ignore") # Function to check data complexity def is_complex(data): variance = np.var(data) return variance > 1000000 # Function to create dataset for LSTM def create_dataset(dataset, time_step=1): X, y = [], [] for i in range(len(dataset) - time_step - 1): X.append(dataset[i:(i + time_step), 0]) y.append(dataset[i + time_step, 0]) return np.array(X), np.array(y) def forecast_sales(file): # Read CSV data = pd.read_csv(GlobalTech_Inc_SalesData.csv) # Clean data data = data.dropna() data['Order Date'] = pd.to_datetime(data['Order Date']) data['Total Sales'] = pd.to_numeric(data['Total Sales'], errors='coerce') data = data.drop_duplicates().sort_values(by='Order Date') # Forecasting time_step = 10 forecast_type = "" if is_complex(data['Total Sales']): forecast_type = "LSTM" elif len(data) < 30: forecast_type = "ARIMA" else: forecast_type = "Hybrid" # Prepare forecasting if forecast_type == "LSTM": scaler = MinMaxScaler() scaled_data = scaler.fit_transform(data[['Total Sales']]) X, y = create_dataset(scaled_data, time_step) X = X.reshape(X.shape[0], X.shape[1], 1) lstm_model = Sequential([ LSTM(50, return_sequences=True, input_shape=(X.shape[1], 1)), Dropout(0.2), LSTM(50), Dropout(0.2), Dense(1) ]) lstm_model.compile(optimizer='adam', loss='mean_squared_error') lstm_model.fit(X, y, epochs=5, batch_size=32, verbose=0) lstm_predictions = lstm_model.predict(X) lstm_predictions = scaler.inverse_transform(lstm_predictions) forecast = pd.DataFrame({ 'Date': pd.date_range(start=data['Order Date'].iloc[-1], periods=len(lstm_predictions), freq='D'), 'Forecasted_Sales': lstm_predictions.flatten() }) elif forecast_type == "ARIMA": arima_model = ARIMA(data['Total Sales'], order=(5, 1, 0)) arima_result = arima_model.fit() arima_forecast = arima_result.forecast(steps=30) forecast = pd.DataFrame({ 'Date': pd.date_range(start=data['Order Date'].iloc[-1], periods=len(arima_forecast), freq='D'), 'Forecasted_Sales': arima_forecast.flatten() }) else: # Hybrid arima_model = ARIMA(data['Total Sales'], order=(5, 1, 0)) arima_result = arima_model.fit() arima_forecast = arima_result.forecast(steps=30) scaler = MinMaxScaler() scaled_data = scaler.fit_transform(data[['Total Sales']]) X, y = create_dataset(scaled_data, time_step) X = X.reshape(X.shape[0], X.shape[1], 1) lstm_model = Sequential([ LSTM(50, return_sequences=True, input_shape=(X.shape[1], 1)), Dropout(0.2), LSTM(50), Dropout(0.2), Dense(1) ]) lstm_model.compile(optimizer='adam', loss='mean_squared_error') lstm_model.fit(X, y, epochs=5, batch_size=32, verbose=0) lstm_predictions = lstm_model.predict(X) lstm_predictions = scaler.inverse_transform(lstm_predictions) hybrid_forecast = arima_forecast.flatten() + lstm_predictions.flatten()[:len(arima_forecast)] forecast = pd.DataFrame({ 'Date': pd.date_range(start=data['Order Date'].iloc[-1], periods=len(hybrid_forecast), freq='D'), 'Forecasted_Sales': hybrid_forecast }) # Merge for forecast by product data_with_forecast = pd.merge(data, forecast, left_on='Order Date', right_on='Date', how='left') product_sales_forecast = data_with_forecast.groupby('Product Name')['Forecasted_Sales'].sum().reset_index() product_sales_forecast = product_sales_forecast.sort_values(by='Forecasted_Sales', ascending=False) top_product = product_sales_forecast.iloc[0] # Plot fig, ax = plt.subplots(figsize=(10, 6)) sns.barplot(x='Product Name', y='Forecasted_Sales', data=product_sales_forecast, ax=ax, palette='coolwarm') plt.xticks(rotation=45) plt.title("Forecasted Sales by Product") plt.tight_layout() # Save image img = io.BytesIO() plt.savefig(img, format='png') plt.close() img.seek(0) return f"Forecast Model Used: {forecast_type}\nTop-Selling Product: {top_product['Product Name']} with Forecasted Sales: {top_product['Forecasted_Sales']:.2f}", img # Gradio Interface interface = gr.Interface( fn=forecast_sales, inputs=gr.File(label="Upload Sales CSV File"), outputs=["text", gr.Image(type="pil")], title="Sales Forecasting App", description="Upload a CSV file with columns: Order Date, Product Name, Total Sales to forecast sales and identify top-selling products." ) if __name__ == "__main__": interface.launch()