Varför blir det olika resultat?
Jag har en numpy array value_function med nS element som jag uppdaterar tills den konvergerar.
Mitt problem: jag förstår inte varför det blir ett annat (felaktigt) resultat om jag kommenterar bort rad 3 i följande kodstycke (dvs value_function = np.zeros(nS)):
while not (np.max(np.abs(value_function-value_function_old)) < tol):
value_function_old = value_function
value_function = np.zeros(nS)
for s in range(nS):
a = policy[s]
value_function[s] = np.sum([tuple[0]*tuple[2] + gamma * tuple[0]*value_function_old[tuple[1]] for tuple in P[s][a]])
För mig känns det som att den raden är helt onödig, jag går ändå igenom hela value_function och skriver över varje element så det borde inte spela någon roll om den tidigare bara va nollor eller om de har sina gamla värden. Eftersom det blir olika resultat för mig så verkar det ju uppenbarligen inte vara så att det jag tror händer (alla element skrivs över) är vad som faktiskt händer, så vad är det jag missar?
Edit: Jag inser att det kanske är så att elementen skrivs över, men att det är något annat som gör att hela koden agerar annorlunda. När jag tar bort while-loopen och ersätter med en for-loop och kör ett fixt antal iterationer verkar det bli samma. Men faktum kvarstår att den enda skillnaden är den raden. (ändrade rubrik pga denna insikt)
Jag hjälper gärna till, men jag har inte använt numpy mycket (däremot Python). Har du ett fullständigt program jag kan leka med?
Laguna skrev:Jag hjälper gärna till, men jag har inte använt numpy mycket (däremot Python). Har du ett fullständigt program jag kan leka med?
Ja jag har ett fullständigt program, men det är en del filer så jag vet inte om det är värt att sätta sig in i all kod. (Det är dock hela loopen jag skrivit där) Jag vet inte om det är så mycket numpy som spökar utan snarare hur den utvärderar while-loopen eller något liknande. För som sagt, om jag sätter att den ska köras något fixt antal iterationer så verkar jag få samma resultat, med eller utan den tredje raden.
Om du ändå vill har koden så kan jag hitta ett lämpligt sätt att lägga upp det på.
Det är nog så här enkelt: när du har tilldelat value_function_old ett värde så pekar den och value_function på samma sak, så att om du ändrar en cell i den ena så ändras den andra. Därför behöver value_function få en ny vektor. Vad den innehåller är däremot inte viktigt.
Laguna skrev:Det är nog så här enkelt: när du har tilldelat value_function_old ett värde så pekar den och value_function på samma sak, så att om du ändrar en cell i den ena så ändras den andra. Därför behöver value_function få en ny vektor. Vad den innehåller är däremot inte viktigt.
Det kanske ska sägas att jag lärt mig Python själv så vissa (kanske grundläggande, men ibland viktiga) detaljer har jag missat. Det verkar vara precis som du säger:
>>> import numpy as np
>>> a = np.zeros(3)
>>> b = np.zeros(3)
>>> b = a
>>> a[2]=2
>>> a
array([0., 0., 2.])
>>> b
array([0., 0., 2.])
Då är det inte så konstigt att den "hoppar ur" while-loopen tidigare när value_function_old fortsätter att uppdateras, skillnaden blir ju då 0.
Ett annat sätt än att göra
value_function_old = value_function
value_function = np.zeros(nS)
är att göra
value_function_old = value_function.copy()
Då delar variablerna inte minne längre, och den andra raden behövs inte. Men det här gäller bara om value_function är nånting som har copy-metoden definierad, som t.ex. en lista. Om det fungerar på ett sånt här np-objekt vet jag inte. Det kan också vara så att np-objektet har en djupare struktur än en vanlig lista, och då räcker inte copy-metoden, för den kopierar bara högsta nivån, inte allting. I så fall kan man göra så här:
import copy
value_function_old = copy.deepcopy(value_function)
Förmodligen är den ursprungliga koden att föredra.
.copy() verkar vara en metod som finns för numpy arrays, även value_function_old = np.copy(value_function) verkar fungera och troligtvis vad jag borde använt.