Spaces:
Runtime error
Runtime error
Commit
·
fcba0b8
1
Parent(s):
e8d91c4
Add demo explanation
Browse files- app.py +9 -1
- helpers/thompson_sampling.py +21 -6
app.py
CHANGED
@@ -187,12 +187,20 @@ st.markdown("""We immediately notice that the demand (and profit) posteriors are
|
|
187 |
apart this time around which implies that we are more confident in our predictions.""")
|
188 |
st.markdown("Now, we can sample just one curve from the distribution.")
|
189 |
st.image(["assets/images/posterior_demand_sample_2.png", "assets/images/posterior_profit_sample_2.png"])
|
190 |
-
st.markdown("""And finally we arrive at a price point of €4.
|
191 |
the actual optimum of €4.24""")
|
192 |
|
193 |
# (5) Thompson sampling demo
|
194 |
st.header("Demo time 🎮")
|
195 |
st.markdown("Now that we have covered the theory, you can go ahead and try it our for yourself!")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
|
197 |
thompson_sampler = ThompsonSampler()
|
198 |
demo_button = st.checkbox(
|
|
|
187 |
apart this time around which implies that we are more confident in our predictions.""")
|
188 |
st.markdown("Now, we can sample just one curve from the distribution.")
|
189 |
st.image(["assets/images/posterior_demand_sample_2.png", "assets/images/posterior_profit_sample_2.png"])
|
190 |
+
st.markdown("""And finally we arrive at a price point of €4.04 which is eerily close to
|
191 |
the actual optimum of €4.24""")
|
192 |
|
193 |
# (5) Thompson sampling demo
|
194 |
st.header("Demo time 🎮")
|
195 |
st.markdown("Now that we have covered the theory, you can go ahead and try it our for yourself!")
|
196 |
+
st.markdown("""You will notice a few things: \n
|
197 |
+
👉 As you increase price elasticity, the demand becomes more sensitive to price changes and thus the
|
198 |
+
profit-optimizing price becomes lower (& vice versa). \n
|
199 |
+
👉 As you decrease price elasticity, our demand observations at €7.5, €10 and €11 become
|
200 |
+
increasingly larger and increasingly more variable (as their variance is a constant fraction of the
|
201 |
+
absolute value). This causes our demand posterior to become increasingly wider and thus Thompson
|
202 |
+
sampling will lead to more exploration.
|
203 |
+
""")
|
204 |
|
205 |
thompson_sampler = ThompsonSampler()
|
206 |
demo_button = st.checkbox(
|
helpers/thompson_sampling.py
CHANGED
@@ -70,11 +70,12 @@ class ThompsonSampler:
|
|
70 |
plt.violinplot(price_distr, vert=False, showextrema=False)
|
71 |
|
72 |
for price in self.price_samples:
|
73 |
-
plt.plot(price, 1, marker='o', markersize = 5, color='grey')
|
74 |
|
75 |
plt.axhline(1, color='black')
|
76 |
-
plt.axvline(self.latent_price, 0, color='red')
|
77 |
|
|
|
78 |
return fig
|
79 |
|
80 |
def create_posteriors_plot(self, highlighted_sample=None):
|
@@ -84,13 +85,21 @@ class ThompsonSampler:
|
|
84 |
plt.xlim(0,20)
|
85 |
plt.ylim(0,10)
|
86 |
|
87 |
-
plt.scatter(self.price_observations, self.demand_observations)
|
88 |
-
plt.plot(self.possible_prices, self.latent_demand, color="red")
|
89 |
|
90 |
for posterior_sample in self.posterior_samples:
|
91 |
-
plt.plot(
|
|
|
|
|
|
|
92 |
if highlighted_sample is not None:
|
93 |
-
plt.plot(
|
|
|
|
|
|
|
|
|
|
|
94 |
return fig
|
95 |
|
96 |
def calc_latent_demand(self):
|
@@ -128,3 +137,9 @@ class ThompsonSampler:
|
|
128 |
if st.session_state.latent_elasticity != self.latent_elasticity:
|
129 |
self.update_elasticity()
|
130 |
self.pick_posterior()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
plt.violinplot(price_distr, vert=False, showextrema=False)
|
71 |
|
72 |
for price in self.price_samples:
|
73 |
+
plt.plot(price, 1, marker='o', markersize = 5, color='grey', label="Price sample")
|
74 |
|
75 |
plt.axhline(1, color='black')
|
76 |
+
plt.axvline(self.latent_price, 0, color='red', label="Latent optimal price")
|
77 |
|
78 |
+
_plot_legend()
|
79 |
return fig
|
80 |
|
81 |
def create_posteriors_plot(self, highlighted_sample=None):
|
|
|
85 |
plt.xlim(0,20)
|
86 |
plt.ylim(0,10)
|
87 |
|
88 |
+
plt.scatter(self.price_observations, self.demand_observations, label="Demand observations")
|
89 |
+
plt.plot(self.possible_prices, self.latent_demand, color="red", label="Latent demand")
|
90 |
|
91 |
for posterior_sample in self.posterior_samples:
|
92 |
+
plt.plot(
|
93 |
+
self.possible_prices, posterior_sample,
|
94 |
+
color="grey", alpha=0.15, label="Posterior demand"
|
95 |
+
)
|
96 |
if highlighted_sample is not None:
|
97 |
+
plt.plot(
|
98 |
+
self.possible_prices, highlighted_sample,
|
99 |
+
color="black", label="Thompson sampled demand"
|
100 |
+
)
|
101 |
+
|
102 |
+
_plot_legend()
|
103 |
return fig
|
104 |
|
105 |
def calc_latent_demand(self):
|
|
|
137 |
if st.session_state.latent_elasticity != self.latent_elasticity:
|
138 |
self.update_elasticity()
|
139 |
self.pick_posterior()
|
140 |
+
|
141 |
+
def _plot_legend():
|
142 |
+
handles, labels = plt.gca().get_legend_handles_labels()
|
143 |
+
labels, ids = np.unique(labels, return_index=True)
|
144 |
+
handles = [handles[i] for i in ids]
|
145 |
+
plt.legend(handles, labels, loc='upper right')
|