ositamiles commited on
Commit
b082906
·
verified ·
1 Parent(s): ef27746

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +287 -0
app.py ADDED
@@ -0,0 +1,287 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import matplotlib.pyplot as plt
5
+ from sklearn.preprocessing import LabelEncoder, StandardScaler
6
+ from sklearn.model_selection import train_test_split
7
+ import tensorflow as tf
8
+ from tensorflow.keras.models import Sequential, Model
9
+ from tensorflow.keras.layers import LSTM, Dense, Input, MultiHeadAttention, LayerNormalization
10
+ from tensorflow.keras.optimizers import Adam
11
+ import joblib
12
+ import os
13
+ import openai
14
+ from stable_baselines3 import PPO
15
+ from stable_baselines3.common.vec_env import DummyVecEnv
16
+ from gym import spaces
17
+
18
+ # Set page config
19
+ st.set_page_config(page_title="Advanced Dynamic Game Pricing App", layout="wide")
20
+
21
+ # OpenAI API key
22
+ openai.api_key = "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"
23
+
24
+ # Function to load or create data
25
+ @st.cache_data
26
+ def load_data():
27
+ if os.path.exists('game_data.csv'):
28
+ return pd.read_csv('game_data.csv')
29
+ else:
30
+ # Sample dataset with time series data
31
+ data = {
32
+ 'game_id': np.repeat(range(1, 21), 50),
33
+ 'date': np.tile(pd.date_range(start='2020-01-01', periods=50), 20),
34
+ 'genre': np.repeat(np.random.choice(['RPG', 'FPS', 'Strategy', 'Puzzle', 'Sports'], 20), 50),
35
+ 'region': np.repeat(np.random.choice(['Africa', 'NA', 'EU', 'Asia', 'SA'], 20), 50),
36
+ 'demand_index': np.random.uniform(0.1, 1.0, 1000),
37
+ 'competitor_price': np.random.uniform(20, 60, 1000),
38
+ 'past_sales': np.random.randint(100, 1000, 1000),
39
+ 'price': np.random.uniform(25, 65, 1000)
40
+ }
41
+ df = pd.DataFrame(data)
42
+ df.to_csv('game_data.csv', index=False)
43
+ return df
44
+
45
+ # Load data
46
+ df = load_data()
47
+
48
+ # LSTM Model
49
+ def create_lstm_model(input_shape):
50
+ model = Sequential([
51
+ LSTM(64, return_sequences=True, input_shape=input_shape),
52
+ LSTM(32),
53
+ Dense(1)
54
+ ])
55
+ model.compile(optimizer='adam', loss='mse')
56
+ return model
57
+
58
+ # Transformer Model
59
+ def transformer_encoder(inputs, head_size, num_heads, ff_dim, dropout=0):
60
+ x = MultiHeadAttention(key_dim=head_size, num_heads=num_heads, dropout=dropout)(inputs, inputs)
61
+ x = LayerNormalization(epsilon=1e-6)(x)
62
+ res = x + inputs
63
+ x = Dense(ff_dim, activation="relu")(res)
64
+ x = Dense(inputs.shape[-1])(x)
65
+ return LayerNormalization(epsilon=1e-6)(x + res)
66
+
67
+ def create_transformer_model(input_shape):
68
+ inputs = Input(shape=input_shape)
69
+ x = transformer_encoder(inputs, head_size=256, num_heads=4, ff_dim=4, dropout=0.1)
70
+ x = GlobalAveragePooling1D()(x)
71
+ outputs = Dense(1)(x)
72
+ return Model(inputs, outputs)
73
+
74
+ # RL Environment
75
+ class PricingEnv(gym.Env):
76
+ def __init__(self, data):
77
+ super(PricingEnv, self).__init__()
78
+ self.data = data
79
+ self.current_step = 0
80
+ self.action_space = spaces.Box(low=0, high=100, shape=(1,), dtype=np.float32)
81
+ self.observation_space = spaces.Box(low=0, high=np.inf, shape=(6,), dtype=np.float32)
82
+
83
+ def step(self, action):
84
+ reward = self._get_reward(action)
85
+ self.current_step += 1
86
+ done = self.current_step >= len(self.data)
87
+ obs = self._get_observation()
88
+ return obs, reward, done, {}
89
+
90
+ def reset(self):
91
+ self.current_step = 0
92
+ return self._get_observation()
93
+
94
+ def _get_observation(self):
95
+ obs = self.data.iloc[self.current_step][['demand_index', 'competitor_price', 'past_sales', 'genre_encoded', 'region_encoded']].values
96
+ return np.append(obs, self.current_step)
97
+
98
+ def _get_reward(self, action):
99
+ price = action[0]
100
+ actual_price = self.data.iloc[self.current_step]['price']
101
+ return -abs(price - actual_price)
102
+
103
+ # Function to get LLM analysis
104
+ def get_llm_analysis(game_info, market_info):
105
+ prompt = f"""
106
+ Analyze the following game and market information for pricing strategy:
107
+
108
+ Game Information:
109
+ {game_info}
110
+
111
+ Market Information:
112
+ {market_info}
113
+
114
+ Based on this information, suggest a pricing strategy and any factors that might influence the game's price.
115
+ Provide your analysis in a structured format with clear recommendations.
116
+ """
117
+
118
+ response = openai.ChatCompletion.create(
119
+ model="gpt-4",
120
+ messages=[
121
+ {"role": "system", "content": "You are an expert in game pricing and market trends."},
122
+ {"role": "user", "content": prompt}
123
+ ],
124
+ max_tokens=300,
125
+ n=1,
126
+ stop=None,
127
+ temperature=0.7,
128
+ )
129
+
130
+ return response['choices'][0]['message']['content']
131
+
132
+ # Sidebar for navigation
133
+ page = st.sidebar.selectbox("Choose a page", ["Data Explorer", "Model Training", "Price Prediction"])
134
+
135
+ if page == "Data Explorer":
136
+ st.title("Data Explorer")
137
+ st.write(df)
138
+
139
+ st.subheader("Data Statistics")
140
+ st.write(df.describe())
141
+
142
+ st.subheader("Data Visualization")
143
+ fig, ax = plt.subplots(1, 2, figsize=(15, 5))
144
+ ax[0].scatter(df['competitor_price'], df['price'])
145
+ ax[0].set_xlabel('Competitor Price')
146
+ ax[0].set_ylabel('Price')
147
+ ax[0].set_title('Competitor Price vs Price')
148
+
149
+ ax[1].scatter(df['demand_index'], df['price'])
150
+ ax[1].set_xlabel('Demand Index')
151
+ ax[1].set_ylabel('Price')
152
+ ax[1].set_title('Demand Index vs Price')
153
+
154
+ st.pyplot(fig)
155
+
156
+ elif page == "Model Training":
157
+ st.title("Model Training")
158
+
159
+ # Data preprocessing
160
+ le_genre = LabelEncoder()
161
+ df['genre_encoded'] = le_genre.fit_transform(df['genre'])
162
+
163
+ le_region = LabelEncoder()
164
+ df['region_encoded'] = le_region.fit_transform(df['region'])
165
+
166
+ features = ['genre_encoded', 'region_encoded', 'demand_index', 'competitor_price', 'past_sales']
167
+ X = df[features]
168
+ y = df['price']
169
+
170
+ scaler = StandardScaler()
171
+ X_scaled = scaler.fit_transform(X)
172
+
173
+ # Reshape data for LSTM
174
+ X_lstm = X_scaled.reshape((X_scaled.shape[0], 1, X_scaled.shape[1]))
175
+
176
+ # Split the data
177
+ X_train, X_test, y_train, y_test = train_test_split(X_lstm, y, test_size=0.2, random_state=42)
178
+
179
+ # Model training
180
+ if st.button("Train Models"):
181
+ with st.spinner("Training LSTM model..."):
182
+ lstm_model = create_lstm_model((1, X_train.shape[2]))
183
+ lstm_history = lstm_model.fit(X_train, y_train, epochs=50, batch_size=32, validation_split=0.2, verbose=0)
184
+
185
+ with st.spinner("Training Transformer model..."):
186
+ transformer_model = create_transformer_model((1, X_train.shape[2]))
187
+ transformer_history = transformer_model.fit(X_train, y_train, epochs=50, batch_size=32, validation_split=0.2, verbose=0)
188
+
189
+ with st.spinner("Training RL model..."):
190
+ env = DummyVecEnv([lambda: PricingEnv(df)])
191
+ rl_model = PPO("MlpPolicy", env, verbose=0)
192
+ rl_model.learn(total_timesteps=10000)
193
+
194
+ st.success("All models trained successfully!")
195
+
196
+ # Plot training history
197
+ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5))
198
+ ax1.plot(lstm_history.history['loss'], label='LSTM Training Loss')
199
+ ax1.plot(lstm_history.history['val_loss'], label='LSTM Validation Loss')
200
+ ax1.set_xlabel('Epoch')
201
+ ax1.set_ylabel('Loss')
202
+ ax1.legend()
203
+ ax1.set_title('LSTM Training History')
204
+
205
+ ax2.plot(transformer_history.history['loss'], label='Transformer Training Loss')
206
+ ax2.plot(transformer_history.history['val_loss'], label='Transformer Validation Loss')
207
+ ax2.set_xlabel('Epoch')
208
+ ax2.set_ylabel('Loss')
209
+ ax2.legend()
210
+ ax2.set_title('Transformer Training History')
211
+
212
+ st.pyplot(fig)
213
+
214
+ # Save models and preprocessing objects
215
+ lstm_model.save('lstm_model.h5')
216
+ transformer_model.save('transformer_model.h5')
217
+ rl_model.save('rl_model')
218
+ joblib.dump(scaler, 'scaler.pkl')
219
+ joblib.dump(le_genre, 'le_genre.pkl')
220
+ joblib.dump(le_region, 'le_region.pkl')
221
+
222
+ st.info("Models and preprocessing objects saved.")
223
+
224
+ elif page == "Price Prediction":
225
+ st.title("Price Prediction")
226
+
227
+ # Load saved models and objects
228
+ if os.path.exists('lstm_model.h5') and os.path.exists('transformer_model.h5') and os.path.exists('rl_model.zip'):
229
+ lstm_model = tf.keras.models.load_model('lstm_model.h5')
230
+ transformer_model = tf.keras.models.load_model('transformer_model.h5')
231
+ rl_model = PPO.load('rl_model')
232
+ scaler = joblib.load('scaler.pkl')
233
+ le_genre = joblib.load('le_genre.pkl')
234
+ le_region = joblib.load('le_region.pkl')
235
+
236
+ # User input
237
+ genre = st.selectbox("Select Genre", le_genre.classes_)
238
+ region = st.selectbox("Select Region", le_region.classes_)
239
+ demand_index = st.slider("Demand Index", 0.1, 1.0, 0.5)
240
+ competitor_price = st.slider("Competitor Price", 20.0, 60.0, 40.0)
241
+ past_sales = st.slider("Past Sales", 100, 1000, 500)
242
+
243
+ # Prepare input for prediction
244
+ input_data = np.array([[
245
+ le_genre.transform([genre])[0],
246
+ le_region.transform([region])[0],
247
+ demand_index,
248
+ competitor_price,
249
+ past_sales
250
+ ]])
251
+
252
+ input_scaled = scaler.transform(input_data)
253
+ input_reshaped = input_scaled.reshape((1, 1, input_scaled.shape[1]))
254
+
255
+ # Make predictions
256
+ if st.button("Predict Price"):
257
+ lstm_price = lstm_model.predict(input_reshaped)[0][0]
258
+ transformer_price = transformer_model.predict(input_reshaped)[0][0]
259
+ rl_price = rl_model.predict(input_scaled)[0][0]
260
+
261
+ # Get LLM analysis
262
+ game_info = f"Genre: {genre}, Region: {region}, Past Sales: {past_sales}"
263
+ market_info = f"Demand Index: {demand_index}, Competitor Price: {competitor_price}"
264
+ llm_analysis = get_llm_analysis(game_info, market_info)
265
+
266
+ # Display results
267
+ st.success(f"LSTM Predicted Price: ${lstm_price:.2f}")
268
+ st.success(f"Transformer Predicted Price: ${transformer_price:.2f}")
269
+ st.success(f"RL Predicted Price: ${rl_price:.2f}")
270
+
271
+ st.subheader("LLM Pricing Analysis:")
272
+ st.write(llm_analysis)
273
+
274
+ # Visualize the predictions
275
+ fig, ax = plt.subplots(figsize=(10, 5))
276
+ models = ['LSTM', 'Transformer', 'RL', 'Competitor']
277
+ prices = [lstm_price, transformer_price, rl_price, competitor_price]
278
+ ax.bar(models, prices)
279
+ ax.set_ylabel('Price ($)')
280
+ ax.set_title('Price Comparison')
281
+ st.pyplot(fig)
282
+
283
+ st.info("Consider all model predictions and the LLM analysis to make a final pricing decision.")
284
+ else:
285
+ st.warning("Please train the models first!")
286
+
287
+ st.sidebar.info("This app demonstrates advanced dynamic pricing for game codes using LSTMs, Transformers, RL, and LLM analysis.")