Spaces:
Sleeping
Sleeping
File size: 6,339 Bytes
a797471 5a8a1c7 a797471 dbad5ad a797471 f57d6bf 5a8a1c7 606728b a797471 5a8a1c7 a797471 5a8a1c7 a797471 dbad5ad 5a8a1c7 a797471 dbad5ad 606728b a797471 e64c363 a797471 5a8a1c7 606728b 5a8a1c7 a797471 606728b a797471 720abd1 dbad5ad a797471 dbad5ad 5a8a1c7 dbad5ad a797471 dbad5ad 5a8a1c7 720abd1 dbad5ad 5a8a1c7 dbad5ad 5a8a1c7 dbad5ad 5a8a1c7 dbad5ad a797471 dbad5ad a797471 dbad5ad f57d6bf 5a8a1c7 a797471 5a8a1c7 a797471 606728b a797471 5a8a1c7 a41a64b 5a8a1c7 a797471 606728b a797471 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
from collections import defaultdict
import seaborn as sns
import streamlit as st
import streamlit.components.v1 as components
import plotly.graph_objects as go
import plotly.express as px
import numpy as np
import pandas as pd
from scipy.stats import norm
st.set_page_config(page_title='Can you be truly random ?', layout = 'wide', page_icon = 'favicon.jpg', initial_sidebar_state = 'auto')
cm = sns.light_palette("green", as_cmap=True)
# Custom CSS to styles
st.markdown("""
<style>
button {
padding-top: 50px !important;
padding-bottom: 50px !important;
}
</style>
""", unsafe_allow_html=True)
def set_state(x):
if x == 1: st.toast('The journey begins!', icon='π')
st.session_state.stage = x
def reset_game():
set_state(0)
if 'n_buttons' not in st.session_state:
st.session_state.n_buttons = 2
st.session_state.history = []
st.session_state.preds = defaultdict(lambda: defaultdict(int))
st.session_state.pnl = [0]
st.session_state.min = [0]
st.session_state.max = [0]
st.session_state.max_history = 10
if 'stage' not in st.session_state:
reset_game()
st.title('Can your brain be random?')
n_plays = 50
if st.session_state.stage == 0:
st.button('Begin', on_click=set_state, args=[1],use_container_width=True)
st.session_state.n_buttons = st.slider(label="How many buttons to play with?", min_value=2, max_value=5,value=2)
st.markdown(f'You will be presented with {st.session_state.n_buttons} buttons to randomly choose from')
st.markdown(f"At each round, I will try to predict which button you click")
st.session_state.max_history = st.slider(label="How much memory can I use?", min_value=2, max_value=20,value=10)
st.markdown(f"I will examine {st.session_state.max_history}-long sequences you played in the past")
st.markdown('This will help me make a guess')
st.markdown(f"If I get it right, I earn {st.session_state.n_buttons-1} point(s), otherwise you earn 1 point")
st.subheader(f'This is a fair game, as you have {(1-1/st.session_state.n_buttons):.0%} chances of winning')
st.markdown(f"Play as long as you want and try to beat me!")
st.markdown(f"I will start showing you my strategy from {n_plays} rounds")
def make_pred(max_history=st.session_state.max_history,alpha=2):
history = st.session_state.history
denominator = 0
scores = {str(i):0 for i in range(st.session_state.n_buttons)}
recent = np.array(history[-max_history:])
data = []
for i in range(1,len(history)):
past = np.array(history[-i-max_history:-i])
played = history[-i]
decay = np.exp(-alpha*np.linspace(1,0,len(past)))
same = past == recent[-len(past):]
similarity = (same*decay).sum() / decay.sum()
weight = np.exp(-alpha*i/(len(history)+1)) * similarity # len(history)/(len(history)+i) * similarity
scores[played] += weight
denominator += weight
if similarity > 0.5:
data.append([played,similarity,weight,i] + [None]* (max_history-len(past)) +list(same))
if not denominator:
return get_random_play(),data
result = {str(i):scores[str(i)]/denominator for i in range(st.session_state.n_buttons)}
return result, data
def get_random_play():
return {str(i):1/st.session_state.n_buttons for i in range(st.session_state.n_buttons)}
def update_pnl(user_win):
current_score = st.session_state.pnl[-1]
current_score += -1 if user_win else (st.session_state.n_buttons-1)
st.session_state.pnl.append(current_score)
expected_change = (2**0.5) * ((st.session_state.n_buttons-1)/st.session_state.n_buttons)
st.session_state.min.append(st.session_state.min[-1]-expected_change)
st.session_state.max.append(st.session_state.max[-1]+expected_change)
def user_select(i,choice):
st.session_state.history.append(str(i))
if i == choice:
st.toast("I win!", icon='π€ͺ')
update_pnl(user_win=False)
else:
st.toast('Well done!', icon='π')
update_pnl(user_win=True)
# refresh_preds()
def compute_perf():
data = np.array(st.session_state.pnl)
if len(data) > 1:
data = data[1:] - data[:-1]
perf = data.mean()
std = data.std()
win = (data>0).mean()
sharpe = perf / std
return win,sharpe
else:
return 0,0
if st.session_state.stage == 1:
pred,data = make_pred()
choice = max(pred,key=pred.get)
progress = min(1.,float(len(st.session_state.history))/n_plays)
my_bar = st.progress(progress)
cols = st.columns(st.session_state.n_buttons)
for i,col in enumerate(cols):
col.button(str(i),on_click=user_select, args=[str(i),choice],
use_container_width=True)
col1,col2 = st.columns(2)
win,sharpe = compute_perf()
if progress >= 1.:
if sharpe > 0.1:
emoticon = "π"
elif sharpe < 0:
emoticon = "π"
else:
emoticon = "π§ "
text = f'%age win={win:.0%} Sharpe={sharpe:.3f} {emoticon}'
col1.subheader('My earnings so far...')
col1.write(text)
dev = abs(st.session_state.pnl[-1] / st.session_state.max[-1])
chance = 1 - norm.cdf(dev)
col1.write(f'There is only {chance:.2%} chances of achieving this by chance')
fig = px.line(st.session_state.pnl)
fig.update_layout(showlegend=False)
fig.update_layout(xaxis={'visible': True, 'showticklabels': False})
col1.plotly_chart(fig, use_container_width=True)
cols = ['you_played','similarity','weight','how_long_ago'] + [f'same_{i}' for i in range(st.session_state.max_history)]
data = pd.DataFrame(data,columns=cols).set_index('how_long_ago').sort_values('weight',ascending=False)[:10]
col2.subheader(f'In the past, you played')
col2.dataframe(data.style.background_gradient(cmap=cm), use_container_width=True)
won = choice == st.session_state.history[-1]
col2.write(f'So I chose {choice} (p={pred[choice]:.0%}) and ' + ('won π' if won else 'lost π'))
st.button('Start over', on_click=reset_game, args=[],
use_container_width=True) |