A mátrixszorzás számos rendszerben használt alapvető művelet, a neurális hálózatoktól a tudományos számítási rutinokig. Hatékony és bizonyíthatóan helyes algoritmusok megtalálása a mátrixszorzáshoz óriási hatással lehet a számítások gyorsabbá és hatékonyabbá tételére, de ez egy nagyon nagy kihívást jelentő feladat. A lehetséges algoritmusok tere óriási, és az algoritmusok felfedezésének hagyományos módszerei, mint például az ember által tervezett heurisztika vagy a kombinatorikus keresés, gyakran szuboptimálisak.
DeepMindA közelmúltban javasolt, mesterséges intelligencia-alapú megoldása az automatizált kereséshez messze túlmutat az emberi intuíción. A megoldás egy AlphaTensor nevű mélyerősítő tanulási ügynökből áll, amelyre épül alfanulla. Ezt az ügynököt egy egyjátékos TensorGame játékra képezték ki, ahol a cél az, hogy számításilag hatékony algoritmusokat fedezzen fel a mátrixszorzáshoz.
Az AlphaTensor különösen jól kezeli a nagy mátrixokat azáltal, hogy a nagy mátrixszorzásokat kisebb szorzásokra bontja. Ezenkívül az AlphaTensor a legkorszerűbb teljesítmény elérésére használható a mátrixszorzáshoz, miután egy adott hardvereszközön finomhangolták.
Az AlphaTensor nagy lehetőségeket rejt magában a mélytanulási számítástechnika felgyorsításában. A mély tanulásban sok időigényes művelet leképezhető mátrixszorzásokra. Az AlphaTensor használatával e műveletek optimalizálására a mélytanulási modellek általános teljesítménye jelentősen javítható.
Nemrég az OpenAlphaTensor, a Az AlphaTensor első nyílt forráskódú implementációjamegjelent, ami forradalmasíthatja a mély tanulási modellek számítási teljesítményét.
Mátrixszorzás tenzor
A mátrixszorzás optimalizálásában nem jártasak számára nem biztos, hogy egyszerű megérteni, hogyan lehet egy műveletet, például a mátrixszorzást leképezni egy háromdimenziós tenzorban. Megpróbálom egyszerű szavakkal és példákkal elmagyarázni.
Tekintsük a C = A*B szorzatot, ahol az egyszerűség kedvéért A és B is N méretű négyzetmátrix. A szorzási művelet leképezhető egy 3D alakú tenzorral (N^2, N^2, N^2). Az első tenzordimenzió az A lapított mátrixot, a második a B lapított mátrixot, a harmadik dimenzió a C lapított mátrixot jelenti.
A tenzornak csak bináris értékei (1 vagy 0) vannak minden bejegyzéshez. Figyeljük meg, hogy a tenzor a szorzási műveletet reprezentálja, tehát független az A és B mátrixok értékétől.
A tenzor minden bejegyzése megfelel a műveleti együtthatónak. Például a C[1,1] kiszámításához meg kell szorozni az A[1,1]-t és a B[1,1]-t is. Ezért a tenzor bejegyzés [0,0,0], amely megfelel az A[1,1], B[1,1] és C[1,1] értékeknek, 1 lesz. Ezzel szemben a C[1,1 kiszámításához ,2,1], A[1] nem szükséges. Így a T[N+0, :, XNUMX] tenzorsor csak nullákat fog tartalmazni.
Az alábbi képen egy példa látható N=2 tenzorra.
Kép a DeepMind's-től papír kiadva Természet
Amint az a fenti ábra (b) és (c) pontjában látható, lehetséges egy algoritmus a szorzat kiszámítására a 3D tenzor dekompozíciójával. Pontosabban, az alábbi algoritmus használható tenzorbontás (az U, V, W mátrixok) mátrixszorzó algoritmussá alakítására.
A DeepMind-ben bevezetett C=AB mátrixszorzat kiszámításához paraméterezett meta-algoritmus papír
A TensorGame
A mátrixszorzáshoz hatékony algoritmusok megtalálásának problémája rendkívül nagy kihívást jelent, mivel a figyelembe veendő lehetséges algoritmusok száma sokkal nagyobb, mint az univerzum atomjainak száma, még kis mátrixszorzás esetén is.
A DeepMind ezt a problémát egyjátékos játékká alakította át, és TensorGame-nek nevezte el. Ebben a játékban a játékos kiválasztja, hogyan kombinálja a mátrixok különböző bejegyzéseit a szorzáshoz. A pontozás a helyes szorzási eredmény eléréséhez szükséges műveletek száma alapján történik. A játék akkor ér véget, amikor elérjük a nulla tenzort, vagy amikor a maximális számú lépést megtettük. A végső faktorizációt a maradék rang becslése és bizonyos optimalizálási kritériumok, például az aszimptotikus időbonyolítás vagy a gyakorlati futási idő alapján értékelik.
A TensorGame kezdeti pozíciója megfelel a mátrixszorzó tenzornak, amelyet valamilyen véletlenszerű alapon fejeznek ki.
A játék minden t lépésében a játékos felír három vektort
, amely a rang-1 tenzorokat határozza meg . A játék állapota a játékos által kiválasztott vektorok kivonásával frissül:
ahol
a mátrixszorzó tenzor.
Ha a játék p lépésben végződik, ez azt jelenti, hogy a Mátrixszorzás Tenzor
p rank-1 tenzorokra bontható , azaz legalább p rangja van.
A TensorGame ezután rangfelbontási algoritmusként értelmezhető, az AlphaTensor pedig a tenzor rangjának becslésére szolgáló algoritmus.
AlphaTensor architektúra
Eddig megismertük a TensorGame-et, és tisztáztuk, hogyan tekinthető a megoldása mátrixszorzó algoritmusnak. Vizsgáljuk meg most az AlphaTensor, a játékhoz használt algoritmus főbb fogalmait.
Az AlphaTensor architektúra alapvetően egy kódoló-dekódoló Transformer architektúra, ahol:
- a kódoló bemenetként a játék állapotát veszi fel , a modell által végrehajtott n korábbi művelet (általában n=7), és az aktuális művelet t időindexe. Az információ egy tenzorba van halmozva, amelynek alakja (n+1, N^2, N^2, N^2). Ezt a tenzort ezután átformálják és (három lineáris réteg felhasználásával) egy alaktenzorrá alakítják (N^2, N^2, c), ahol c a modell belső dimenziója.
- a dekóder a kódoló által megadott beágyazott vektorból autoregresszív módon generálja az n_steps műveleteket. Minden művelet a hármasok egy jelzőjének felel meg a játék tenzorát lebontó (azaz a rangját csökkentő) hármasok egyikének ábrázolása
A modellt a visszaszaporítás és a modellszínészet váltakozva képezi. A modelleljárás az adatok generálására szolgál, amelyeket aztán a modell betanításához használnak fel. A gyakorlatban a modellt szintetikusan generált adatok és a modell által a cselekvés során generált adatok keverékével képezik. A színészi lépés úgy történik, hogy veszünk egy mátrixműveletnek megfelelő 3D tenzort, és n_actors játékokat játszunk rajta. Minden szereplő vagy standard alapon, vagy alternatív alapon játszik egy játékot (a bázisváltást adott valószínűséggel alkalmazzák). Az eredményeket ezután összegyűjtik, és a szintetikus adatokkal együtt felhasználhatják a képzési lépésben.
A színészi lépés az AlphaZero Monte Carlo Tree Search (MCTS) programján alapul, amelyet úgy módosítottak, hogy támogassa a nagy akciótereket. Röviden, a művelet kiválasztása előtt az n_sims útvonalakat feltárja a modell kimenetéből, legfeljebb 5 lépésből álló jövőbeli feltárással. A modell által generált valószínűségeket ezután a generált útvonalak figyelembevételével korrigálják. Ezután a legígéretesebb jövőbeli út(ok)kal rendelkező akció kerül kiválasztásra a játék folytatásához.
A modell képzése közben a jutalom valójában negatív jutalom (büntetés). Abszolút értéke minden további lépéssel növekszik, amely a játék megoldásához szükséges. Ha a modell m lépést tesz meg egy TensorGame megoldásához, a játékhoz tartozó jutalom r=-m. Ha a modell nem tudja megoldani a TensorGame-et max_rank lépésekben, akkor a jutalmat a fennmaradó tenzor rangjának becslésével számítjuk ki. A rangot a tenzort alkotó mátrixok rangsorainak összegeként becsüljük. A becslés a tenzor valódi rangjának felső korlátja.
A modell finomhangolásakor a végállapotú büntetés jutalomnak figyelembe kell vennie a modell által előállított algoritmus késleltetését is. A jutalomképlet a következőképpen alakul: rt'=rt+λbt, ahol rt a korábban leírt jutalmazási séma, bt a benchmark jutalom (nem nulla csak a végállapotban), és λ egy felhasználó által megadott együttható.
Az AlphaTensor által felfedezett, GPU-ra és TPU-ra szabott algoritmusok felgyorsítása (%), a DeepMind papírjából kinyerve. A gyorsulásokat a szabványos (pl. cuBLAS a GPU-hoz) mátrixszorzáshoz viszonyítva mérik ugyanazon a hardveren, és összehasonlítják a Strassen-négyzet algoritmus. forrás: DeepMind.
Nemrég szabadultam OpenAlphaTensor, az AlphaTensor első nyílt forráskódú megvalósítása. Ebben a részben a megvalósítást fogom végigjárni. Amint azt korábban tárgyaltuk, az AlphaTensor architektúra meglehetősen egyszerű, szabványos transzformátoron alapul, kódoló-dekódoló architektúrával. Az AlphaTensor legérdekesebb összetevői a kódoló rész első rétege és a műveletek mintavételi módja.
Kezdjük az első kódolási réteggel.
# x.size = (N, T, S, S, S)
# scalars.size = (N, s)
batch_size = x.shape[0]
S = x.shape[-1]
T = x.shape[1]
x1 = x.permute(0, 2, 3, 4, 1).reshape(batch_size, S, S, S * T)
x2 = x.permute(0, 4, 2, 3, 1).reshape(batch_size, S, S, S * T)
x3 = x.permute(0, 3, 4, 2, 1).reshape(batch_size, S, S, S * T)
input_list = [x1, x2, x3]
for i in range(3): temp = self.linears_1[i](scalars).reshape(batch_size, S, S, 1) input_list[i] = torch.cat([input_list[i], temp], dim=-1) input_list[i] = self.linears_2[i](input_list[i])
x1, x2, x3 = input_list
A fenti részletben bemutatjuk, hogyan bomlik fel a bemeneti tenzor három tenzorra, amelyeket aztán a transzformátorréteg lekérdezés-, kulcs- és értékbemeneteként használunk.
- A lapított mátrixokat reprezentáló három tenzordimenzióban (A, B, C) a bemeneti tenzor az egyes dimenziók mentén lelapul az előző műveleteket reprezentáló dimenzióval együtt. Ily módon a bemeneti tenzor minden egyes lapított másolatában a kiválasztott dimenzió az utolsó T-1 értékek és a tényleges érték összesítése a kiválasztott dimenzió összes S értékére vonatkozóan, ahol S=N^2. Filozófiailag olyan, mintha minden dimenzió esetében arra összpontosítanánk, ami az adott dimenzióban az előző cselekvések során történt.
- A skalárokat három különböző, S^2 méretű térben leképezzük, majd átformázzuk, hogy az előző pontban kapott tenzorokkal összekapcsolódjanak. Elméletileg a skalárokat egy S^2 dimenziójú beágyazási térre képezik le, majd a beágyazott információkat S vektorokká csonkolják, és egymásba rakják, hasonlóan ahhoz, ami a szöveggel tokenizáláskor történik.
- A skalár tokeneket összefűzzük az átstrukturált bemeneti tenzorral, majd bemenetként egy lineáris réteghez adjuk a skalárok+csatornatörténet fókuszinformációinak leképezéséhez a modell belső dimenziójában.
Ez a három lépés úgy értelmezhető, mint egy módja annak, hogy a modellnek információt adjon a skalárokról (mint a TensorGame időlépésében), és az egyes csatornák előző műveleteire összpontosítson.
Ami a műveletek előállítási módját illeti, érdekes megjegyezni, hogy az AlphaTensor kimenetként az u, v, w tripletet generálja, ami a tenzorrangsor csökkentését célozza. A három vektor S méretű, és mivel össze vannak kapcsolva, a modellnek egy 3*S méretű vektort kell előállítania. Az AlphaTensor RL algoritmussal van kiképezve, így minden lehetséges cselekvést valószínűségekkel kell kifejezni egy felsorolt térben, azaz a modell a különböző cselekvésekre valószínűséget állít elő. Ez azt jelenti, hogy a 3S térben minden vektort más-más művelethez kell leképezni. Ez |F|^(3S) méretű akcióteret eredményez, ahol |F| a különböző értékek száma, amelyet u, v, w eleme felvehet. Általában az értékek a (-2, -1, 0, 1, 2) értékre korlátozódnak, ami 5 elemű kardinalitást eredményez.
Itt jön egy nagy kihívás: az 5-ös méretű mátrixok mátrixszorzatának cselekvési valószínűségeinek generálásához 5^75 * 4 bájtos memóriára van szükségünk, ami ~10^44 GB memóriát jelent. Nyilvánvaló, hogy ilyen nagy akcióteret nem tudunk kezelni.
Hogyan oldjuk meg a problémát? A cselekvési valószínűségek memórialábnyomának csökkentése érdekében a hármasokat kisebb darabokra bonthatjuk, „tokenizálhatjuk”, és a darabokat generált tokenként kezeljük a transzformátor architektúrában, azaz a tokenek bemenetként adódnak a dekóderhez auto-regresszív módon. út. A fenti példában a hármasokat 15 darabra oszthatjuk, így a memóriafelhasználást 15 * 5^(75/15) * 4-re, azaz 187.5 KB-ra csökkentjük.
def _eval_forward(self, e: torch.Tensor): bs = e.shape[0] future_g = ( torch.zeros((bs, self.n_samples, self.n_steps)).long().to(e.device) ) ps = torch.ones((bs, self.n_samples)).to(e.device) e = e.unsqueeze(1).repeat(1, self.n_samples, 1, 1) future_g = future_g.view(-1, self.n_steps) ps = ps.view(-1) e = e.view(-1, e.shape[-2], e.shape[-1]) for i in range(self.n_steps): o_s, z_s = self.core(future_g[:, : i + 1], e) future_g[:, i], p_i = sample_from_logits(o_s[:, i]) ps *= p_i future_g = future_g.view(bs, self.n_samples, self.n_steps) ps = ps.view(bs, self.n_samples) return ( future_g, ps, z_s[:, 0].view(bs, self.n_samples, *z_s.shape[2:]).mean(1), )
A fentiekben bemutatjuk a teljes művelet generálásához szükséges kódrészletet. A kódban a self.core tartalmazza a dekódoló réteget, az e tenzor pedig a kódoló réteg kimenetét jelenti. A nullát úgy tekinthetjük, mint a Az NLP modellekben a token és az n_steps darabokat reprezentáló n_steps műveletek progresszív módon jönnek létre.
A modell három mennyiséget ad vissza:
- A generált műveletek
- A teljes művelethez kapcsolódó valószínűség
- Az első művelet (az első csonk) generálásához előállított logitok, amelyeket a modell értékének kiszámításához használnak majd.
Érdemes néhány szót szánni az n_samples paraméterre. A paramétert a cselekvési lépéshez használják, és lehetővé teszi a modell számára, hogy a hármasok különböző verzióit állítsa elő, amelyeket azután a cselekvési folyamatban használt Monte Carlo Tree Search algoritmus akcióterének feltárására használnak fel. Az n_samples különböző műveletek mintavételezése a modell által generált házirend szerint történik.
Színészi lépés
Az egész algoritmus legtrükkösebb része valószínűleg a TensorGame megoldásához használt cselekvési lépés. Az algoritmust az AlphaTensor cikk nem magyarázza mélyrehatóan, mivel az a DeepMind számos korábbi tanulmányán alapul, amelyeket csak idézett és ismertként ad meg. Itt rekonstruálom az összes hiányzó részt, és lépésről lépésre elmagyarázom a megvalósításunkat.
A cselekvési lépéseket három különböző komponensbe szervezhetjük:
- A Monte-Carlo-i fakeresés
- A játék szimulációja
- A továbbfejlesztett házirend-számítás
Elemezzük őket egyenként.
Monte-Carlo Tree Search (MCTS)
A Monte Carlo Tree Search (MCTS) egy széles körben használt mesterséges intelligencia technika a játékban, különösen a társasjátékokban és a videojátékokban. Az algoritmus létrehoz egy játékfát, amely szimulálja a lehetséges lépéseket és az eredményeket, és véletlenszerű mintavételt használ az egyes lépések várható jutalmazásának értékeléséhez. Az algoritmus ezután iteratív módon kiválasztja a legmagasabb várható jutalommal járó lépést, és szimulálja az eredményeket, amíg el nem éri a terminális állapotot vagy egy meghatározott leállási feltételt. A szimulációkat arra használják, hogy megbecsüljék a győzelem valószínűségét minden lépésnél, és irányítsák a döntéshozatali folyamatot. Az MCTS hatékonynak bizonyult olyan összetett játékokban, ahol a lehetséges lépések és kimenetelek száma nagy, és sikeresen játszható mesterséges intelligenciarendszerekben, például az AlphaGo-ban használták.
Az AlphaTensor az eredeti MCTS módosított változatát használja. Pontosabban, ahelyett, hogy véletlenszerűen választanánk ki a műveletet a teljes cselekvési térből, a műveletet a modell által közvetlenül generált részhalmazok közül választják ki (a korábban bemutatott n_samples segítségével). A házirend-frissítés korrekciója ezután a Továbbfejlesztett házirend számítási lépésben kerül alkalmazásra.
Megvalósításunk során úgy döntöttünk, hogy a Monte-Carlo fáról szóló összes információt egy szótárban tároljuk, amelynek kulcsa a TensorGame állapot hash-verziója, értéke pedig magához az állapothoz kapcsolódó információ. Minden Monte-Carlo lépés egy csomópontból indul, és n_sim minijátékokat szimulál, és 5 lépésből álló horizonttal fedezi fel a jövőt. Ha a csomópontot már feltárták a korábbi szimulációkban, akkor az n_sim az előző felderítések számának figyelembevételével módosul. Minden csomópontnál a látogatások számát az N_s_a tenzor tárolja, mivel ez a tenzor tartalmazza a látogatások számát csomópont gyermekműveletenként (a modell által mintavételezettek között).
def monte_carlo_tree_search( model: torch.nn.Module, state: torch.Tensor, n_sim: int, t_time: int, n_steps: int, game_tree: Dict, state_dict: Dict,
): """Runs the monte carlo tree search algorithm. Args: model (torch.nn.Module): The model to use for the simulation. state (torch.Tensor): The initial state. n_sim (int): The number of simulations to run. t_time (int): The current time step. n_steps (int): The maximum number of steps to simulate. game_tree (Dict): The game tree. state_dict (Dict): The dictionary containing the states. """ state_hash = to_hash(extract_present_state(state)) if state_hash in state_dict: with torch.no_grad(): N_s_a = state_dict[state_hash][3] n_sim -= int(N_s_a.sum()) n_sim = max(n_sim, 0) for _ in range(n_sim): simulate_game(model, state, t_time, n_steps, game_tree, state_dict) # return next state possible_states_dict, _, repetitions, N_s_a, q_values, _ = state_dict[ state_hash ] possible_states = _recompose_possible_states(possible_states_dict) next_state_idx = select_future_state( possible_states, q_values, N_s_a, repetitions, return_idx=True ) next_state = possible_states[next_state_idx] return next_state
A fenti kód az algoritmus mikénti megvalósítását mutatja. A kód egyszerűsítése érdekében a házirend-javítás a simulate_game függvényben történik.
Játék szimuláció
A simulate_game függvény a TensorGame egy adott állapotát képviselő csomópontokból álló fa feltárásáért felelős. Ezenkívül lefuttatja a modellt, amikor egy levélcsomóponttal találkozik, és az összes csomópontinformációt a state_dict szótárban tárolja. Vessünk egy mély pillantást a megvalósítására:
@torch.no_grad()
def simulate_game( model, state: torch.Tensor, t_time: int, max_steps: int, game_tree: Dict, states_dict: Dict, horizon: int = 5,
): """Simulates a game from a given state. Args: model: The model to use for the simulation. state (torch.Tensor): The initial state. t_time (int): The current time step. max_steps (int): The maximum number of steps to simulate. game_tree (Dict): The game tree. states_dict (Dict): The states dictionary. horizon (int): The horizon to use for the simulation. """ idx = t_time max_steps = min(max_steps, t_time + horizon) state_hash = to_hash(extract_present_state(state)) trajectory = [] # selection while state_hash in game_tree: ( possible_states_dict, old_idx_to_new_idx, repetition_map, N_s_a, q_values, actions, ) = states_dict[state_hash] possible_states = _recompose_possible_states(possible_states_dict) state_idx = select_future_state( possible_states, q_values, N_s_a, repetition_map, return_idx=True ) trajectory.append((state_hash, state_idx)) # state_hash, action_idx future_state = extract_present_state(possible_states[state_idx]) state = possible_states[state_idx] state_hash = to_hash(future_state) idx += 1 # expansion if idx = max_steps: trajectory.append((state_hash, None)) if not game_is_finished(extract_present_state(state)): state = state.to(model.device) scalars = get_scalars(state, idx).to(state.device) actions, probs, q_values = model(state, scalars) ( possible_states, cloned_idx_to_idx, repetitions, not_dupl_indexes, ) = extract_children_states_from_actions( state, actions, ) not_dupl_actions = actions[:, not_dupl_indexes].to("cpu") not_dupl_q_values = torch.zeros(not_dupl_actions.shape[:-1]).to( "cpu" ) N_s_a = torch.zeros_like(not_dupl_q_values).to("cpu") present_state = extract_present_state(state) states_dict[to_hash(present_state)] = ( _reduce_memory_consumption_before_storing(possible_states), cloned_idx_to_idx, repetitions, N_s_a, not_dupl_q_values, not_dupl_actions, ) game_tree[to_hash(present_state)] = [ to_hash(extract_present_state(fut_state)) for fut_state in possible_states ] leaf_q_value = q_values else: leaf_q_value = -int(torch.linalg.matrix_rank(state).sum()) # backup backward_pass(trajectory, states_dict, leaf_q_value=leaf_q_value)
Minden szimuláció három részre oszlik:
- Kiválasztás
- Terjeszkedés
- mentés
A kiválasztási részben a szimuláció a már generált fa-csomópontokon fut le, és a következő csomópontot választjuk ki a következő függvény segítségével:
def select_future_state( possible_states: List[torch.Tensor], q_values: torch.Tensor, N_s_a: torch.Tensor, repetitions: Dict[int, list], c_1: float = 1.25, c_2: float = 19652, return_idx: bool = False,
) -> torch.Tensor: """Select the future state maximizing the upper confidence bound."""
# q_values (1, K, 1) pi = torch.tensor( [ len(repetitions[i]) for i in range(len(possible_states)) if i in repetitions ] ).to(q_values.device) ucb = q_values.reshape(-1) + pi * torch.sqrt( torch.sum(N_s_a) / (1 + N_s_a) ) * (c_1 + torch.log((torch.sum(N_s_a) + c_2 + 1) / c_2)) if return_idx: return ucb.argmax() return possible_states[ucb.argmax()]
A gyakorlatban az ucb függvényt maximalizáló művelet:
az adott állapothoz van kiválasztva. Itt Q a modell által generált Q értékeket jelöli, π pedig a véletlenszerű eloszlást a modellházirend segítségével mintavételezett műveletek között. N(s, a) jelenti a csomópont látogatásainak számát az a művelethez az s csomóponttól.
Amint a kiválasztási fázis elér egy levél csomópontot, és ha a szimuláció nem ért el egy végső feltételt (akár a maximális feltárás, azaz a jövő horizontja, akár a játék befejezése szempontjából), a modellt ezután az n_samples alternatív csomópontok kiválasztására használják (ezek levél lesz csomópontok az egymást követő iterációban). Ezt nevezzük bővítési fázisnak, mivel új csomópontok kerülnek a fába. Ezután az aktuális szimulációban nincs további csomópont feltárása, hanem a levél q_értéke elküldésre kerül a következő szimulációs lépéshez: a biztonsági mentés.
A biztonsági mentés minden szimuláció utolsó szakasza. A biztonsági mentés során, ha a levélcsomópont terminál állapotú volt, a rendszer kiszámítja a végső jutalmat; egyébként a levél q értékét használjuk becsült jutalomként. Ezután a jutalom visszaterjed a szimulációs pályán, frissítve mind a q_values állapotokat, mind pedig az N(s, a) látogatásszámlálót. Az alábbi részletben a jutalom visszaterjesztésének kódját mutatjuk be.
def backward_pass(trajectory, states_dict, leaf_q_value: torch.Tensor): """Backward pass of the montecarlo algorithm"""
reward = 0 for idx, (state, action_idx) in enumerate(reversed(trajectory)): if action_idx is None: # leaf node reward += leaf_q_value else: ( _, old_idx_to_new_idx, _, N_s_a, q_values, _, ) = states_dict if isinstance(reward, torch.Tensor): reward = reward.to(q_values.device) action_idx = int(action_idx) if action_idx in old_idx_to_new_idx: not_dupl_index = old_idx_to_new_idx[int(action_idx)] else: not_dupl_index = action_idx reward -= 1 q_values[:, not_dupl_index] = ( N_s_a[:, not_dupl_index] * q_values[:, not_dupl_index] + reward ) / (N_s_a[:, not_dupl_index] + 1) N_s_a[:, not_dupl_index] += 1
Továbbfejlesztett házirend-számítás
Miután az összes szimuláció lefutott, és az MCTS érdekes pillanatképet kínál a közeljövőről, ideje frissíteni az előre jelzett csomópontokhoz tartozó szabályzatot, és visszaadni őket, hogy felhasználhassák őket a képzés során. A továbbfejlesztett házirend, a pontban leírt módszert követve Hubert et al, nagy akcióterek kezelésére szolgál. Valójában kis keresési terület esetén lehetséges az MCTS során véletlenszerűen mintát venni egy akcióból az akciótérből, és kiértékelni a hatását. Hasonló megközelítés egy sokkal nagyobb cselekvési térben ahhoz vezetne, hogy minden pálya különböző utakon tér el, és végtelen mennyiségű pályára lenne szükség az értelmes statisztikák készítéséhez, majd a politika frissítéséhez. Mivel itt a minta-MCTS-t használjuk a diszperzió elkerülésére, azaz n_samples műveletek mintavételezése a modell házirendjének megfelelően történik, majd az MCTS csak kiválaszt egyet a mintavételezett műveletek közül a fa feltárása során, ezért számításnál figyelembe kell venni a mintakorrekciót. a végső frissített szabályzat, amelyet a modell betanítása során használunk.
A gyakorlatban a javított házirendet a következőképpen számítják ki
ahol
def compute_improved_policy( state_dict: Dict, states: List[str], model_n_steps: int, model_n_logits: int, N_bar: int,
): """Compute the improved policy given the state_dict, the list of states. The improved policy is computed as (N_s_a / N_s_a.sum())^(1/tau) where tau is (log(N_s_a.sum()) / log(N_bar)) if N_s_a.sum() > N_bar else 1. """ policies = torch.zeros(len(states), model_n_steps, model_n_logits) N_bar = torch.tensor(N_bar) for idx, state in enumerate(states): N_s_a = state_dict[3] actions = state_dict[5] if N_s_a.sum() > N_bar: tau = (torch.log(N_s_a.sum()) / torch.log(N_bar)).item() else: tau = 1 N_s_a = N_s_a ** (1 / tau) improved_policy = N_s_a / N_s_a.sum() for sample_id in range(actions.shape[1]): action_ids = actions[0, sample_id] for step_id, action_id in enumerate(action_ids): policies[idx, step_id, action_id] += improved_policy[ 0, sample_id ] return policies
Vegye figyelembe, hogy megvalósításunkban, miután kiszámítottuk a házirendet az N_s_a tenzorból, vissza kell képeznünk az eredeti művelettenzorra. Valójában az N_s_a csak a modell által mintavételezett műveleteket veszi figyelembe, míg a végső szabályzatnak tartalmaznia kell valószínűségeket a fel nem vizsgált műveletekre is.
Különbségek a ChatGPT képzési algoritmussal kapcsolatban
Az AlphaTensor a DeepMind mesterséges intelligencia módszereinek AlphaGo/AlphaZero családjának legújabb tagja. Ezek a módszerek a Monte Carlo Tree Search (MCTS) algoritmuson alapulnak, amelyet a DeepMind finomított és továbbfejlesztett az egyre összetettebb feladatok megoldására. Egy másik mesterséges intelligencia rendszer, az OpenAI ChatGPT, amely nagy feltűnést keltett figyelemreméltó teljesítménye miatt, egy másik megközelítéssel, az RLHF-nek (Reforcement Learning with Human Feedback) lett kiképezve.
Az RLHF egy finomhangoló technika, amellyel a nyelvi modelleket úgy hangolják, hogy egy sor írott utasítást kövessenek. Az emberi preferenciákat jutalomjelként használja a modell finomhangolására, ezáltal a nyelvi modell viselkedését az emberek egy bizonyos csoportjának kinyilvánított preferenciáihoz igazítja, nem pedig az „emberi értékek” valamilyen tágabb fogalmához.
Ezzel szemben az MCTS egy fa alapú keresési algoritmus, amelyet a játékok optimális lépéseinek meghatározására használnak. Simulálja a lehetséges lépéseket, és frissíti az egyes lépések értékeit azok eredményei alapján, irányítva a legjobb lépés kiválasztását.
Az RLHF adatokat gyűjt az emberek által írt bemutatókból és az AI-modellek ember által jelzett összehasonlításából, és egy jutalommodellt képez ki, amely előrejelzi egy adott embercsoport preferenciáit. A jutalommodellt ezután az AI-modellek finomhangolására használják. Az MCTS ezzel szemben szimulációkat és értékeléseket használ a legjobb döntés meghatározásához.
Bár eltérő megközelítésekről van szó, az RLHF és az MCTS hasonlóságokat is mutat. Mindkét mesterséges intelligencia-technika döntéshozatali és problémamegoldó módszereket használ, és mindkettő próba-szerencse megközelítést alkalmaz a különböző lehetőségek feltárására és a rendelkezésre álló információk alapján történő döntéshozatalra. Mindkettő iteratív folyamat, amely idővel javul, ahogy egyre több információ és tapasztalat gyűlik össze.
Az RLHF és az MCTS közötti választás az adott feladattól függ. Az RLHF ideális, ha nincs egyértelmű mérőszám a modell teljesítményének értékelésére, míg az MCTS hatékonynak bizonyult olyan játékszerű feladatokban, ahol a tudás és a jövő feltárása jelentős előnyt jelent a modellnek.
Kódoptimalizálás az AlphaTensor edzéshez
Az AlphaTensor edzési algoritmus megvalósításához meg kell találni a tökéletes kompromisszumot az edzési sebesség és a memóriafelhasználás között. Amint az a Modell részben látható, az akciótokenizálás egyszerű figyelembevétele sok memóriát takaríthat meg, de a túlzottan agresszív akcióterület-csökkentés a pontosság csökkenéséhez és a teljesítmény csökkenéséhez is vezethet. Ez utóbbi azért történik, mert az összes tokent szekvenciálisan, autoregresszív módon generálja a modelldekóder. Ezért a következtetési idő lineárisan növekszik a műveletenkénti tokenek számával, miután az akciótér softmax-ja már nem jelenti a szűk keresztmetszetet.
Az AlphaTensor tréning felállításakor a fő nehézségeket a színészi folyamat kezelésében találtuk. Ha a tenzorokat nem a megfelelő formátumban tárolják, az MCTS könnyen ellenőrizetlen memóriahasználat-növekedést okozhat. Másrészt, ha az egyes szimulációk során tárolt tenzorok számát túlságosan csökkentik, az MCTS végtelenül sok időt tölthet a szükséges állapotok újraszámításával.
Vegyünk egy példát a játék szimulációs lépésére, ahol a játékot a lehetséges jövőbeli forgatókönyvek megvizsgálásával tárják fel. Ha minden egyes állapot esetében nem mentjük el a modell által generált műveleteket, és úgy döntünk, hogy csak azt a véletlen magot mentjük, amelyet a házirendből a műveletek mintavételezésére használtunk, akkor minden egyes facsomópont felfedezésekor újra kell számolnunk a házirendet, és majd mintát kell venni a műveletekből. Nyilvánvalóan úgy döntöttünk, hogy a mintavételezett műveleteket tároljuk, hogy időt takarítsunk meg, és ne kelljen modellmegosztást kezelni a különböző folyamatok között az MCTS feltárás párhuzamosítása esetén. A cselekvések elmentése azonban nem volt elegendő a kellően hatékony színészi lépéshez. Valójában az n_steps műveletek (u, v, w) hármassá alakításának, a játék tenzorállapotának csökkentésének és az n_samples akciókból az új3D tenzorok létrehozásának ideje könnyen szűk keresztmetszetet jelentene az egész képzés számára. Másodszor, nem akartuk az összes lehetséges jövőbeli állapotot eltárolni minden egyes mintavételezett művelethez, mivel ez óriási hatással lenne az algoritmus által használt memóriára. Tegyük fel, hogy beállítjuk az n_samples=32, n=7 és N=5 értékeket, és ne feledjük, hogy N a csökkenteni kívánt négyzetmátrixszorzat mérete, n pedig a modell által megjegyzett korábbi műveletek száma. Ebben a helyzetben minden állapottenzor alakja (8, 25, 25, 25) lenne, ami 32-vel szorozva 32-t eredményezne.82525254 bájt a grafikon minden csomópontjához. Ha figyelembe vesszük, hogy a bővítési fázisban minden szimuláció egy új csomópontot generál (és n_sim=200), a végső memóriafelhasználásunk 200 lenne.328252525*4 = 3.2 GB egyedül az első MCTS-csomóponthoz. A legrosszabb forgatókönyv szerint a működő max_rank csomópontok (ahol max_rank = 150) feltárása esetén ez 150 * 3.2 GB = 480 GB teljes memóriafelhasználást eredményezne a RAM memóriában (vagy a GPU memóriájában, ha minden tenzor a GPU-n van tárolva). . A képzést a munkaállomásunkon 128 GB RAM-mal és 48 GB GPU memóriával bonyolítottuk le, így csökkenteni kellett a memóriafelhasználást.
Mivel nem akartuk megnövelni a végrehajtási időt, ezért olyan optimalizálást alkalmaztunk, amely kihasználja az előállított állapottenzorok redundanciáját. Valójában a tenzoroknak n-1 közös korábbi műveletük van, amelyeket azután egyszer el lehet tárolni, és nem ismételhetők meg minden tárolt tenzornál. Ez 2/7-28%-os memóriacsökkenést eredményez, ami azt jelenti, hogy legrosszabb esetben 137 GB tárolható. Ezen a ponton a fa fel nem használt részének (például a nem kiválasztott pályák) egyszerűen lemetszésével és a tenzorok CPU memóriájában való tárolásával elkerülhettük a memóriahibákat a képzés során.
Mivel az OpenAlphaTensor nyílt forráskódú, számos izgalmas út nyílik a további fejlesztésre.
Természetes folyamat az OpenAlphaTensor finomhangolása a célhardvereken. Ez várhatóan nagyon versenyképes számítási teljesítményhez vezet. Többet fogok közzétenni az OpenAlphaTensor teljesítményéről különböző hardvereken GitHub. A cikk írásakor az OpenAlphaTensor képzésen vett részt.
Egy másik fontos előrelépés a távoli fordítás támogatása, amely lehetővé teszi a felhasználók számára, hogy szélső eszközökre optimalizált algoritmusokat készítsenek. Ezt úgy érhetjük el, hogy az OpenAlphaTensor modellt egy szerveren tároljuk, míg a mátrixszorzó algoritmust különböző hardvereken értékeljük ki.
Fontos lehet a különböző fordítók támogatásának kiterjesztése a késleltetés alapú jutalomkorrekció kiszámításához. A különböző fordítók különböző optimalizált algoritmusokhoz vezethetnek egy adott hardveren. Például a DeepMind dokumentum ígéretes eredményeket mutatott a JAX és az XLA fordító használatával TPU és Nvidia GPU-kon. Érdekes lenne ezt kiértékelni az NCCL segítségével Nvidián vagy LLVM-mel a CPU-kon.
Végül továbbra is komoly nyitott kihívás marad a modell és a betanító algoritmus kiterjesztése a nagyobb mátrixméretek támogatására. Az OpenAlphaTensor jelenleg 5-ös maximális mátrixméretet támogat, de alkalmazható úgy, hogy a nagyobb mátrixszorzásokat apró, 5-nél kisebb méretű MM-csoportokra osztja. Ez a megközelítés szuboptimális, és a redukciót közvetlenül a nagy tenzoron hajtja végre, amely megfelel a A teljes MM elméletileg jobb eredményekhez vezethet.
Diego Fiori a Nebuly AI technológiai igazgatója, amely vállalat elkötelezett amellett, hogy az AI-optimalizálást minden fejlesztő eszköztárának részévé tegye.
- SEO által támogatott tartalom és PR terjesztés. Erősödjön még ma.
- Platoblockchain. Web3 metaverzum intelligencia. Felerősített tudás. Hozzáférés itt.
- Forrás: https://www.kdnuggets.com/2023/03/first-open-source-implementation-deepmind-alphatensor.html?utm_source=rss&utm_medium=rss&utm_campaign=first-open-source-implementation-of-deepminds-alphatensor
- :is
- ][p
- $ UP
- 1
- 3d
- 8
- a
- Képes
- Rólunk
- felett
- Abszolút
- gyorsuló
- Szerint
- Eszerint
- Fiók
- pontosság
- Elérése
- elért
- Akció
- cselekvések
- tulajdonképpen
- hozzáadott
- További
- Beállított
- fogadott
- előre
- Előny
- Után
- Ügynök
- összesítés
- agresszív
- AI
- AI rendszerek
- célok
- algoritmus
- algoritmusok
- Minden termék
- lehetővé téve
- lehetővé teszi, hogy
- kizárólag
- már
- alternatív
- között
- összeg
- elemez
- és a
- Másik
- alkalmazott
- megközelítés
- megközelít
- építészet
- VANNAK
- cikkben
- mesterséges
- mesterséges intelligencia
- AS
- kijelölt
- társult
- At
- Automatizált
- elérhető
- elkerülve
- vissza
- mentés
- alapján
- Alapvetően
- alap
- BE
- mert
- válik
- előtt
- hogy
- lent
- benchmark
- BEST
- Jobb
- között
- Túl
- bizottság
- Társasjátékok
- köteles
- tágabb
- BT
- épít
- épült
- by
- hívott
- TUD
- nem tud
- eset
- Okoz
- okozott
- bizonyos
- kihívás
- kihívást
- változik
- csatorna
- ChatGPT
- gyermek
- választás
- választja
- választott
- idézett
- világos
- világosan
- kód
- összegyűjti
- össze
- elkötelezett
- Közös
- vállalat
- képest
- versenyképes
- bonyolult
- bonyolultság
- alkatrészek
- áll
- kompromisszum
- számítás
- számítási teljesítmény
- Kiszámít
- számítástechnika
- fogalmak
- fogalmilag
- feltétel
- bizalom
- Fontolja
- figyelembe vett
- figyelembe véve
- úgy véli,
- fogyasztás
- tartalmaz
- folytatódik
- kontraszt
- átalakított
- Mag
- Megfelelő
- megfelel
- tudott
- Számláló
- CPU
- teremt
- létrehozása
- kritériumok
- CTO
- Jelenlegi
- Jelenleg
- dátum
- foglalkozó
- dönt
- határozott
- döntés
- Döntéshozatal
- határozatok
- mély
- mély tanulás
- DeepMind
- függ
- leírt
- Határozzuk meg
- Fejlesztő
- Fejlesztés
- eszköz
- Eszközök
- DICT
- különböző
- nehézségek
- Dimenzió
- méretek
- közvetlenül
- felfedez
- felfedezése
- tárgyalt
- terjesztés
- megosztott
- le-
- Csepp
- alatt
- e
- minden
- Korábban
- könnyen
- él
- Hatékony
- hatékony
- bármelyik
- elem
- elemek
- beágyazott
- vége
- fokozott
- hatalmas
- elég
- belépés
- hiba
- becslés
- becsült
- Eter (ETH)
- értékelni
- értékelték
- értékelő
- értékelések
- Még
- Minden
- példa
- példák
- izgalmas
- végrehajtás
- terjeszkedés
- várható
- tapasztalat
- Magyarázza
- magyarázható
- hasznosítja
- kutatás
- feltárása
- feltárt
- Feltárása
- kifejezve
- terjed
- kiterjedő
- rendkívüli módon
- meglehetősen
- család
- gyorsabb
- Visszacsatolás
- kevés
- Ábra
- utolsó
- megtalálása
- vezetéknév
- Úszó
- Összpontosít
- következik
- következő
- Lábnyom
- A
- forma
- formátum
- képlet
- talált
- ból ből
- Tele
- funkció
- alapvető
- további
- további fejlődés
- jövő
- játék
- Games
- generál
- generált
- generál
- generáló
- kap
- szerzés
- Ad
- adott
- Giving
- cél
- Goes
- jó
- GPU
- GPU
- grafikon
- nagy
- Csoport
- Csoportok
- növekszik
- Növekedés
- útmutató
- kéz
- Kezelés
- történt
- megtörténik
- hardver
- hardver eszköz
- hardvereszközök
- Legyen
- tekintettel
- itt
- legnagyobb
- horizont
- Hogyan
- How To
- azonban
- HTTPS
- hatalmas
- emberi
- i
- BETEG
- ideális
- IDX
- kép
- Hatás
- végre
- végrehajtás
- fontos
- javul
- javított
- in
- Növelje
- Növeli
- egyre inkább
- független
- index
- információ
- kezdetben
- bemenet
- helyette
- utasítás
- Intelligencia
- érdekes
- belső
- Bevezetett
- intuíció
- IT
- ismétlés
- ITS
- maga
- jpg
- KDnuggets
- Tart
- Kulcs
- tudás
- ismert
- nyelv
- nagy
- nagyobb
- keresztnév
- Késleltetés
- legutolsó
- réteg
- tojók
- vezet
- tanult
- tanulás
- Lista
- néz
- keres
- Sok
- készült
- Fő
- fontos
- csinál
- Gyártás
- kezelése
- kezelése
- sok
- térkép
- térképészet
- Mátrix
- Anyag
- maximális
- jelenti
- jelentőségteljes
- eszközök
- tag
- Memory design
- módszer
- mód
- metrikus
- hiányzó
- keverék
- modell
- modellek
- módosított
- modul
- több
- hatékonyabb
- Ráadásul
- a legtöbb
- mozog
- mozog
- szorozva
- Természetes
- Természet
- Közel
- elengedhetetlen
- Szükség
- szükséges
- negatív
- hálózatok
- ideg-
- neurális hálózatok
- Új
- következő
- NLP
- csomópont
- csomópontok
- nem szakértők
- fogalom
- szám
- Nvidia
- kapott
- of
- Ajánlatok
- on
- ONE
- nyitva
- nyílt forráskódú
- OpenAI
- működés
- Művelet
- optimálisan
- optimalizálás
- Optimalizálja
- optimalizált
- Opciók
- eredeti
- Más
- másképp
- teljesítmény
- átfogó
- Papír
- papírok
- paraméter
- rész
- különös
- különösen
- alkatrészek
- Emberek (People)
- tökéletes
- teljesítmény
- előadó
- fázis
- darabok
- Plató
- Platón adatintelligencia
- PlatoData
- játszani
- játékos
- játék
- pont
- Politikák
- politika
- pozíció
- lehetséges
- potenciális
- hatalom
- Gyakorlati
- gyakorlat
- előre
- jósolt
- preferenciák
- bemutatott
- előző
- valószínűség
- valószínűleg
- Probléma
- folyamat
- Folyamatok
- gyárt
- Készült
- Termékek
- haladás
- progresszív
- biztató
- javasolt
- bizonyíthatóan
- igazolt
- közzétesz
- közzétett
- RAM
- véletlen
- soraiban
- Inkább
- elérte
- Elér
- nemrég
- csökkenteni
- Csökkent
- csökkentő
- kifinomult
- megerősítő tanulás
- felszabaduló
- megmaradó
- maradványok
- figyelemre méltó
- eszébe jut
- távoli
- megismételt
- képviselő
- jelentése
- kötelező
- megköveteli,
- felelős
- korlátozott
- eredményez
- kapott
- Eredmények
- visszatérés
- Visszatér
- forradalmasítani
- Jutalom
- SOR
- rt
- futás
- s
- azonos
- Megtakarítás
- megtakarítás
- forgatókönyv
- forgatókönyvek
- rendszer
- Keresés
- Második
- Rész
- mag
- kiválasztott
- kiválasztása
- kiválasztás
- MAGA
- készlet
- beállítás
- számos
- Alak
- megosztás
- rövid
- kellene
- előadás
- mutatott
- Műsorok
- Jel
- jelentős
- jelentősen
- hasonló
- hasonlóságok
- Egyszerű
- egyszerűség
- egyszerűen
- tettetés
- óta
- helyzet
- Méret
- méretek
- kicsi
- kisebb
- Pillanatkép
- So
- megoldások
- SOLVE
- Megoldása
- néhány
- forrás
- Hely
- terek
- különleges
- kifejezetten
- meghatározott
- sebesség
- költ
- Költési
- osztott
- négyzet
- egymásra rakva
- Színpad
- standard
- kezdet
- kezdődik
- Állami
- csúcs-
- meghatározott
- Államok
- statisztika
- Lépés
- Lépései
- megállítás
- tárolni
- memorizált
- árnyékolók
- egyértelmű
- sikeres
- ilyen
- támogatás
- Támogatja
- szintetikus
- szintetikus adatok
- szintetikusan
- rendszer
- Systems
- szabott
- Vesz
- tart
- bevétel
- cél
- Feladat
- feladatok
- technikák
- terminál
- feltételek
- hogy
- A
- A jövő
- A grafikon
- az információ
- Az állam
- azok
- Őket
- ezáltal
- ebből adódóan
- Ezek
- Harmadik
- három
- háromdimenziós
- Keresztül
- idő
- időigényes
- nak nek
- együtt
- jelképes
- tokenizálás
- Vezérjeles
- tokenek
- is
- eszköztár
- felső
- fáklya
- Végösszeg
- hagyományos
- Vonat
- kiképzett
- Képzések
- vonatok
- röppálya
- át
- kezelésére
- igaz
- megért
- Világegyetem
- felhasználatlan
- Frissítések
- frissítve
- Frissítés
- frissítése
- frissítés
- us
- Használat
- használ
- Felhasználók
- rendszerint
- érték
- Értékek
- különféle
- változat
- videó
- videojátékok
- Látogat
- Látogatók
- W
- Út..
- Mit
- ami
- míg
- széles körben
- Wikipedia
- lesz
- nyerő
- val vel
- szavak
- munkaállomás
- érdemes
- lenne
- írás
- írott
- X
- zephyrnet
- nulla