Spaces:
Paused
Paused
Add file
Browse files- meta2frame.py +137 -0
meta2frame.py
ADDED
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import glob
|
2 |
+
import tqdm
|
3 |
+
import pickle
|
4 |
+
import os
|
5 |
+
import datetime
|
6 |
+
|
7 |
+
import torch
|
8 |
+
import bittensor as bt
|
9 |
+
import pandas as pd
|
10 |
+
import plotly.express as px
|
11 |
+
|
12 |
+
def trust(W, S, threshold=0):
|
13 |
+
"""Trust vector for subnets with variable threshold"""
|
14 |
+
|
15 |
+
# assert (S.sum()-1).abs()<1e-4, f'Stake must sum to 1, got {S.sum()}'
|
16 |
+
Wn = (W > 0).float()
|
17 |
+
return Wn.T @ S
|
18 |
+
# return ( (W > threshold)*S.reshape(-1,1) ).sum(axis=0)
|
19 |
+
|
20 |
+
def rank(W, S):
|
21 |
+
"""Rank vector for subnets"""
|
22 |
+
# assert (S.sum()-1).abs()<1e-4, f'Stake must sum to 1, got {S.sum()}'
|
23 |
+
|
24 |
+
R = W.T @ S
|
25 |
+
return R / R.sum()
|
26 |
+
|
27 |
+
def emission(C, R):
|
28 |
+
"""Emission vector for subnets"""
|
29 |
+
|
30 |
+
E = C*R
|
31 |
+
return E / E.sum()
|
32 |
+
|
33 |
+
def YC1(T, a=0.5, b=10):
|
34 |
+
"""Yuma Consensus 1"""
|
35 |
+
|
36 |
+
return torch.sigmoid( b * (T - a) )
|
37 |
+
|
38 |
+
|
39 |
+
def load_metagraphs(root_dir, netuid):
|
40 |
+
|
41 |
+
metagraphs = []
|
42 |
+
match_path = os.path.join(root_dir, str(netuid), '*.pkl')
|
43 |
+
files = glob.glob(match_path)
|
44 |
+
print(f'Found {len(files)} metagraphs in {match_path}')
|
45 |
+
for path in tqdm.tqdm(files):
|
46 |
+
|
47 |
+
with open(path, 'rb') as f:
|
48 |
+
metagraph = pickle.load(f)
|
49 |
+
metagraphs.append(metagraph)
|
50 |
+
|
51 |
+
return metagraphs
|
52 |
+
|
53 |
+
|
54 |
+
# TODO: can calculate the emission trend using each subnet or just using root subnet
|
55 |
+
def plot_emission_trend(metagraphs, netuid, max_uids=32):
|
56 |
+
|
57 |
+
df = pd.DataFrame()
|
58 |
+
max_uids = max_uids or max(m.W.shape[1] for m in metagraphs)
|
59 |
+
|
60 |
+
for metagraph in metagraphs:
|
61 |
+
E = m.W.mean(axis=0)
|
62 |
+
df = pd.concat([df, pd.DataFrame({'emission':E}).assign(block=metagraph.block)])
|
63 |
+
|
64 |
+
df.sort_values(by='block', inplace=True)
|
65 |
+
|
66 |
+
fig = px.line(df, x=df.index, y='emission',line_group='',
|
67 |
+
title='Emission Trend',
|
68 |
+
|
69 |
+
width=800, height=600, template='plotly_white')
|
70 |
+
fig.update_xaxes(title_text='Block Height')
|
71 |
+
fig.update_yaxes(title_text='Emission')
|
72 |
+
fig.show()
|
73 |
+
|
74 |
+
return fig
|
75 |
+
|
76 |
+
def block_to_time(blocks):
|
77 |
+
if not isinstance(blocks, pd.Series):
|
78 |
+
blocks = pd.Series(blocks)
|
79 |
+
|
80 |
+
block_time_500k = datetime.datetime(2023, 5, 29, 5, 29, 0)
|
81 |
+
block_time_800k = datetime.datetime(2023, 7, 9, 21, 32, 48)
|
82 |
+
dt = (pd.Timestamp(block_time_800k)-pd.Timestamp(block_time_500k))/(800_000-500_000)
|
83 |
+
return block_time_500k + dt*(blocks-500_000)
|
84 |
+
|
85 |
+
root_dir = os.path.expanduser('~/Desktop/py/opentensor/metagraph/subnets/')
|
86 |
+
|
87 |
+
metagraphs = load_metagraphs(root_dir, 0)
|
88 |
+
metagraphs
|
89 |
+
|
90 |
+
def make_dataframe_old(metagraphs, netuid):
|
91 |
+
df = pd.DataFrame()
|
92 |
+
# max_uids=max(m.W.shape[1] for m in metagraphs)
|
93 |
+
for metagraph in sorted(metagraphs, key=lambda m: m.block):
|
94 |
+
if metagraph.n.item() == 0:
|
95 |
+
print(f'Block {metagraph.block} has no nodes, skipping')
|
96 |
+
continue
|
97 |
+
|
98 |
+
if netuid == 0:
|
99 |
+
W = metagraph.W.float()
|
100 |
+
Sn = (metagraph.S/metagraph.S.sum()).clone().float()
|
101 |
+
|
102 |
+
T = trust(W, Sn)
|
103 |
+
R = rank(W, Sn)
|
104 |
+
C = YC1(T)
|
105 |
+
E = emission(C, R)
|
106 |
+
else:
|
107 |
+
T = metagraph.T
|
108 |
+
R = metagraph.R
|
109 |
+
C = metagraph.C
|
110 |
+
E = metagraph.E
|
111 |
+
|
112 |
+
frame = pd.DataFrame({'Trust':T, 'Rank':R, 'Consensus':C, 'Emission':E, 'uid':range(len(E))}).assign(block=metagraph.block.item(), netuid=netuid)
|
113 |
+
df = pd.concat([df, frame])
|
114 |
+
|
115 |
+
df['alive'] = df.groupby('netuid')['Emission'].transform(lambda x: x > 0)
|
116 |
+
df['owner_take'] = df['Emission'] * 7200 * 0.18
|
117 |
+
df['timestamp'] = block_to_time(df['block'])
|
118 |
+
df['day'] = df['timestamp'].dt.dayofyear
|
119 |
+
df.sort_values(by=['block','netuid'], inplace=True)
|
120 |
+
return df
|
121 |
+
|
122 |
+
def make_dataframe(root_dir, netuid, cols=None):
|
123 |
+
if cols is None:
|
124 |
+
cols = ['stake','emission','trust','validator_trust','dividends','incentive','R', 'consensus','validator_permit']
|
125 |
+
frames = []
|
126 |
+
metagraphs = load_metagraphs(root_dir, netuid)
|
127 |
+
print(f'Loaded {len(metagraphs)} metagraphs for netuid {netuid}')
|
128 |
+
for m in metagraphs:
|
129 |
+
frame = pd.DataFrame({k: getattr(m, k) for k in cols})
|
130 |
+
frame['block'] = m.block.item()
|
131 |
+
frame['timestamp'] = block_to_time(frame['block'])
|
132 |
+
frame['netuid'] = netuid
|
133 |
+
frame['uid'] = range(len(frame))
|
134 |
+
frame['hotkey'] = [axon.hotkey for axon in m.axons]
|
135 |
+
frame['coldkey'] = [axon.coldkey for axon in m.axons]
|
136 |
+
frames.append(frame)
|
137 |
+
return pd.concat(frames).sort_values(by=['timestamp','block','uid'])
|