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'])
|