lunedì 23 agosto 2010

HATTRICK - Scavando in HO!







In questo articolo cerco di fare un po' di luce su come HO! pervenga alle sue stime delle valutazioni di campo. Tutti i files che vedete elencati qui li avete anche nel vostro pc se avete HO! installato, li trovate nella cartella "prediction" di HO!

* defaults.xml, readme.txt, si trovano nella cartelletta "prediction", tralascio epvWeights.mlp, un elenco di pesi per reti neurali a quanto ho capito, predictionTypes.conf che è un semplice elenco delle sottocartelle con i tipi di prediction e skeleton.dat che mi pare che non faccia altro che settare i valori di default per tutto quanto

* nelle sottocartelle ci sono playerstrength.dat, che definisce la forza del giocatore, tactics.dat, che stima l'efficacia delle tattiche e le prediction per le diverse zone di campo: midfield.dat, centraldefense.dat, sidedefense.dat, centralattack.dat, sideattack.dat


Procedo con ordine cominciando dal primo gruppo





1 defaults.xml

Non fa altro che definire dei non meglio specificati "FormulaFactors" che mi lasciano un po' perplesso.



Perplesso perché - come vedete - non si spiegano le assenze di valori nei due rettangoli che ho evidenziato.




2 readme.txt

Questo file spiega un po' tutta la logica, vediamo.


"The rating parameters are split into several files one for each prediction type (midfield, central attack, side defense...). They contain at least
  • one [general] section and
  • one [SKILLNAME] or [SKILLNAME_SIDENAME] section.
  • SKILLNAME is one of {goalkeeping, defending, playmaking, passing, scoring, winger}.
  • SIDENAME is one of {allsides, thisside, middle, otherside} If the SIDENAME is omitted, we take ALLSIDES as default. The SIDENAME is especially usefully for side attack and side defense. In this context, we have to calculate two different ratings for the left side and the right side. A player on the left side has - of course - a higher rating impact for the left attack/defense side than for the right side If we calculate the right side, THISSIDE means right side and OTHERSIDE means left side."


Quindi nei files delle zone di campo troveremo una sezione "generale" e una coi pesi in relazione alle skill e alla zona di campo.

"The players are classified in the following manner:
  • ALLSIDES:___All Players
  • MIDDLE: ____Keeper, Extra Players, Single CD , Single IM, Single FW (if not TowardsWing)
  • THISSIDE: ___CD, IM, FW on this side, if not the only one on this position (cioé ci sono 2 in mezzo). Wingback and Winger on this side
  • OTHERSIDE: _Like THISSIDE, for the opposite side"

Questo consente di distinguere i diversi apporti dei giocatori, ad esempio, riprendendo dei grafici già postati in un altro articolo: questo giocatore relativamente agli apporti laterali si torverà in posizione "MIDDLE" e dividerà il suo apporto al 50% in entrambi i lati



Quest'altro invece si trova in posizione THISSIDE per la difesa laterale sinistra, a cui dà il 100% del suo apporto, non viene citato invece nella difesa destra (sarebbe il giocatore "OTHERSIDE"), per cui ad essa non dà alcun apporto



L'unico OTHERSIDE che troveremo citato sarà l'attaccante TW, che contribuisce all'attacco laterale opposto con la sola skill attacco, con valori circa il 40% di quelli dell'attacco laterale a cui è adiacente.




Poi

"How will the ratings be calculated?
  1. First, HO! parses the parameter file and searches for all [SKILLNAME] and [SKILLNAME_SIDENAME] sections.
  2. After that, HO! calculates the player strength for all players on the SIDENAME's side, based on the player's skill, form, stamina and xp using the parameters from the file playerstrength.dat.
  3. The PlayerStrength is multiplied with the PlayerWeight from the current section in the parameter file.
  4. For all players, PlayerStrength*PlayerWeight is added up.
  5. If there are general options (see below) in this section, they will be applied now.
We do this for every section and sum all these partial ratings together.
Eventually, the general options from the [general] section are applied."


L'ordine mi sembra piuttosto chiaro:
  1. Si cercano le skill e le posizioni rilevanti
  2. Si calcola la FORZA del giocatore, moltiplicando la skill per i parametri di FORMA, RESISTENZA e ESPERIENZA
  3. La FORZA è moltiplicata per i PESI (coefficienti) relativi a quella zona di campo
  4. Si sommano i prodotti "Forza*Pesi" di ogni giocatore
  5. Si applicano eventuali correzioni

viene poi introdotto il file playerstrength.dat definendo tutta una serie di funzioni

"In this file, the options are ALWAYS processed in the following order:
Option___________________Function

skillSubDeltaForLevelY=x____if (skill = Y AND subskill=0) then skill = skill + x
(This is used for unknown subskills, i.e. the player did not get training yet and the user did not enter a subskill offset manually)


skillDelta=x________________skill = skill + x
staminaDelta=x_____________stamina = stamina + x
formDelta=x_______________...
xpDelta=x ________________ ...

staminaMin=x______________if stamina < stamina =" x" formmin="x" xpmin="x" skillmin="x" staminamax="x_____________"> x then stamina = x
formMax=x________________...
xpMax=x
skillMax=x

staminaMultiplier=x__________stamina = stamina * x
formMultiplier=x____________...
xpMultiplier=x
skillMultiplier=x

staminaPower=x_____________stamina = stamina^x (i.e. stamina raised by x)
formPower=x_______________... (Use 0.5 as x for square root)
xpPower=x
skillPower=x

staminaLog=x_______________stamina = log_x(stamina) (i.e. log of stamina with base x)
formLog=x_________________ ... (Use 10 as x for base-10-log)
xpLog=x
skillLog=x

finalStaminaMultiplier=x______stamina = stamina * x
finalFormMultiplier=x
finalXpMultiplier=x
finalSkillMultiplier=x

finalStaminaDelta=x__________stamina = stamina + x
finalFormDelta=x
finalXpDelta=x
finalSkillDelta=x

Now we can calculate the result using these options:
We start with result=skill

resultMultiStamina=x_________result = result * x * stamina
resultMultiForm=x___________...
resultMultiXp=x

resultAddStamina=x__________result = result + x * stamina
resultAddForm=x
resultAddXp=x"



si passa poi a introdurre i "rating files" specifici per ogni zona del campo, anche qui definendo le possibili funzioni

"General options (useable in every section, including [general] and [SKILL]):
They will be applied in the following order:

Option_________________Function

  • squareMod=x __rating = rating + x*rating*rating ________# dirty hack! Should be 0, if possible
  • cubeMod=x____rating = rating + x*rating*rating*rating __# even dirtier hack! Should be 0, if possible"

Tattiche:
  • tacticAIM=x______if Tactic=AIM then ___rating = rating * tacticAIM
  • tacticAOW=x_____if Tactic=AOW then ___rating = rating * tacticAOW
  • tacticCounter=x ...
  • tacticCreative=x
  • tacticPressing=x

Team Spirit
  • TSPreMulti=x ____rating = rating * (yourTS*TSPreMulti)^TSPower # new exponential calc
  • TSPower=x

Casa/Fuori
  • home=x _________if game is home game then ____rating = rating * home
  • away=x _________same for away
  • awayDerby=x ____same for away derby (since HO! 1.401)

PIC/MOTS
  • pic=x __________if you play PIC then ___________rating = rating * pic
  • mots=x ________same for MOTS
  • normal=x ______same for normal

ALLENATORE
  • trainerOff=x_____ if your trainer is offensive then ___rating = rating * trainerOff
  • trainerDef=x _____same for defensive trainer
  • trainerNeutral=x __same for neutral trainer
Correttori
  • multiplier=x _____rating = rating * x
  • delta=x _________rating = rating + x
  • extraMulti=x _____multiplier for extra players (extraIM, extraCD, extraFW)
gli ultimi ora sono posti a 1 dato che non c'è più penalità per i giocatori posti come "extra" in zone centrali.

Infine vengono definite le posizioni a cui applicare i Pesi (Coefficienti):

Player Weights (useable in all [SKILL] sections):

Option Function
allCDs=x ___This weight modifier will be multiplied with every CentralDef
allWBs=x ___This weight modifier will be multiplied with every Wingback
allIMs=x
___This weight modifier will be multiplied with every InnerMid
allWIs=x
___This weight modifier will be multiplied with every Winger
allFWs=x
___This weight modifier will be multiplied with every Forward

keeper=_____x keeper

cd_norm=x
__central defender normal
cd_off=x ____central defender offensive
cd_tw=x ____central defender to wing

wb_norm=x _wingback normal
wb_off=x ___wingback offensive
wb_def=x ___wingback defensive
wb_tm=x ___wingback to middle

im_norm=x _inner midfield norm
im_off=x___ inner midfield offensive
im_def=x___ inner midfield defensive
im_tw=x___ inner midfield to wing

wi_norm=x _winger normal
wi_off=x ___winger offensive
wi_def=x ___winger defensive
wi_tm=x ___winger to middle

fw_norm=x _forward normal
fw_def=x ___forward defensive
fw_tw=x ___forward to wing

extra_cd=x _extra central defender
extra_im=x _extra inner midfield
extra_fw=x _extra forward


e precisato che

Every position can have a .SPECIALTY appended, e.g. "fw_def.technical".
If so, the weight is applied to players with this specialty only
.

infine viene presentato un piccolo esempio

Example 1 (Midfield)
====================
Let's say, we want to predict the midfield parameters.
We have a midfield.dat with the following text:

[general]
multiplier=0.2
delta=0.8
squareMod=0.05
...

[playmaking]
allIMs=0.5 # Multiplier for ALL IMs
im_normal=1
im_off=0.9
extra_im=0.85
...

Therefore the PlayerStrength of all normal IMs is multiplied with 0.5 * 1 = 0.5,
the PlayerStrength of all offensive IMs is multiplied with 0.5 * 0.9 = 0.45 and so on.
After that, everything is added up to the PlaymakingSum.

In the end, the parameters from the [general] section are applied to this PlaymakingSum.
I.e.
PlaymakingSum = PlaymakingSum + squareMod*PlaymakingSum^2
PlaymakingSum = PlaymakingSum * multiplier
PlaymakingSum = PlaymakingSum + delta




I files nelle sottocartelle: i due "generici"
1 playerstrenght.dat


Allora, dopo tante presentazioni qui si comincia a fare sul serio. Il succo di questo file è questo:
riguardo alla SKILL

skillDelta=-1.0
skillMin=0
# SkillSubDeltas:
# Default is to add 0.5 subskill for skills 0 (non existant) up to 7 (solid)
# Uncomment the next line to ignore the skillSubDeltas
#[ignore]
skillSubDeltaForLevel0=0.5
skillSubDeltaForLevel1=0.5
skillSubDeltaForLevel2=0.5
skillSubDeltaForLevel3=0.5
skillSubDeltaForLevel4=0.5
skillSubDeltaForLevel5=0.5
skillSubDeltaForLevel6=0.5
skillSubDeltaForLevel7=0.5


Le skill vengono ridotte tutte di "1", si controlla che non siano sotto a 0, si aggiunge 0.5 per i livelli da 0 (inesistente) a 7 (buono). Quest'ultima aggiunta si basa sul principio che quelle skill non sono probabilmente state allenate e quindi hanno decimali ignoti, a Flattermann è parso saggio porsi nel mezzo e aggiungere a tutti un forfettario 0.5
Io non sono molto d'accordo con questa procedura, perché se è vero che posso accettare un 2,5 e un 3,5 al posto di un 2 e un 3, skill 6 e soprattutto 7 possono essere state allenate e quindi non mi pare il caso di aggiungere ben 0.5 a 7 portandolo a 7.5 (tra l'altro è proprio per questo che se un giocatore eccellente pesa in HO solo 0.5 più di un buono, perché questi bonus forfettari finiscono proprio a 7). Credo sarebbe piu' prudente addolcire la curva e aggiungere un 0.3/0.4 a 6 e un 0.2/0.3 a 7.

Vi sono poi una serie di operazioni su RESISTENZA, FORMA e ESPERIENZA che si riducono alle seguenti formule:

# stamina-Factor =____((stamina+6.5)/14)^0.6
# form-Factor =______((form-0.5)/7)^0.45
# xp-Factor =________1 + 7.16% * RADQ(xp-0.5)


che determinano questa tabella



che vanno applicate al precedente valore di skill

# result = skill
# result = result * 1 * stamina___(resultMultiStamina)

# result = result * 1 * form _____(resultMultiForm)

# result = result * 1 * xp_______(resultMultiXp)




2 tactics.dat

# Autogenerated with PredictionSimulation for HO by flattermann
# TacticLevelPrediction [chisquare=0.269985, using 7268 samples, 6637 runs]
[general]
version = 4.0
delta = 1.000000 # fixed
extraMulti = 0.850000 # fixed
squareMod = 0.000000 # fixed
cubeMod = 0.000000 # fixed

[aim_aow]
postMulti = 0.194912 # err=0.001890
squareMod = 0.009067 # err=0.001452
cubeMod = -0.000351 # err=0.000020

[counter]
postMulti = 0.235751 # err=0.007073
squareMod = 0.022976 # err=0.002754
cubeMod = -0.000422 # err=0.000021
multiPs = 0.923695 # err=0.035743
multiDe = 0.404393 # err=0.013345

[pressing]
postMulti = 0.062717 # err=0.001658
squareMod = 0.035617 # err=0.008675
cubeMod = -0.001443 # err=0.000171

[longshots]
postMulti = 0.001162 # err=0.000047
squareMod = -0.310785 # err=0.050769
cubeMod = 302.472449 # err=38.520727


Intuisco le formule, ma non mi è chiaro come e dove si applichino. Le posto per completezza.




I files nelle sottocartelle: le valutazioni di zona
Infine i files di rating veri e propri, quelli che siamo andati a modificare per elaborare le prediction nella ricerca della scorsa stagione, i valori dei pesi cambiano, per fare l'esempio ho scelto il 442 con 2 difensori centrali e due centrocampisti


1 midfield.dat

allora

[general]
multiplier = 0.250000 # fixed
delta = 1.000000 # fixed


per cui alla fine dovremo dividere tutto per 4 e sommare 1

tacticCounter = 0.930000 # fixed

perdita del 7% col contropiede

home = 1.199529 # err=0.004183
awayDerby = 1.113699 # err=0.007379


+20% se si gioca in casa, +11.3% se si gioca un derby in trasferta

pic = 0.839949 # err=0.003179
mots = 1.109650 # err=0.004748


-16% col PIC e quasi +11% col MOTS

teamspiritPreMulti = 0.147832 # err=0.003676
teamspiritPower = 0.417779 # err=0.005549


su questa sono perplesso... applicando i valori presenti qui i conti non mi tornano...

extraMulti = 1.000 # fixed

qui prima c'era 0.85, una perdita del 15% per il cc aggiunto

squareMod = 0.008504 # err=0.001206
cubeMod = -0.000027 # err=0.000005


sono i modificatori "furbetti" visti sopra, al rating del cc si deve sommare
rating + 0.008504*rating*rating -0.000027*rating*rating*rating

tacticLongshots = 0.950323 # err=0.008919

perdita del 5% del cc con la tattica tiri da lontano


Infine ecco i Pesi in regia per i vari ruoli

[playmaking_allsides]
CD_norm = 0.11328
CD_off = 0.15264
CD_tw = 0.07920
WB_norm = 0.07800
WB_off = 0.10800
WB_def = 0.03100
WB_tm = 0.07800
IM_norm = 0.43056
IM_off = 0.40664
IM_def = 0.40664
IM_tw = 0.37996
WI_norm = 0.21800
WI_off = 0.18300
WI_def = 0.18300
WI_tm = 0.27600
FW_def = 0.18330





2 centraldefense.dat

[general]
multiplier = 0.250000 # fixed
delta = 1.000000 # fixed


come prima alla fine dovrò dividere per 4 e sommare 1

trainerOff = 0.928162 # err=0.003268
trainerDef = 1.196307 # err=0.004050
trainerNeutral = 1.050000 # fixed


-7.2% con l'allenatore offensivo, +19.6% col difensivo, +5% col normale

tacticAOW = 0.858029 # err=0.004653
tacticCreative = 0.930999 # err=0.005163


AOW fa perdere il 14.2%, LI il 7%

extraMulti = 1.000 # fixed

anche questo è un residuo del passato

squareMod = 0.008462 # err=0.000976
cubeMod = -0.000017 # err=0.000003


quindi rating + 0.008462*rating*rating -0.000017*rating*rating*rating

pullback = 0.25

credo che questo significhi guadagno del 25% con il ripiegamento e non il 20% come ipotizzato da GM-Homerjay


Infine ecco i Pesi in difesa e parate per i vari ruoli

[goalkeeping_allsides]
keeper = 0.55750

[defending_allsides]
keeper = 0.26500
CD_norm = 0.60192
CD_off = 0.42048
CD_tw = 0.44976
WB_norm = 0.28000
WB_off = 0.23850
WB_def = 0.29850
WB_tm = 0.42600
IM_norm = 0.21804
IM_off = 0.12374
IM_def = 0.35788
IM_tw = 0.19964
WI_norm = 0.12550
WI_off = 0.05400
WI_def = 0.16750
WI_tm = 0.16000




3 sidedefense.dat


[general]
multiplier = 0.250000 # fixed
delta = 1.000000 # fixed

come prima alla fine dovrò dividere per 4 e sommare 1

trainerOff = 0.927577 # err=0.002694
trainerDef = 1.197332 # err=0.003328
trainerNeutral = 1.050000 # fixed

come per la difesa centrale, -7.2% con l'allenatore offensivo, +19.6% col difensivo, +5% col normale

tacticCreative = 0.930663 # err=0.004241
tacticAIM = 0.853911 # err=0.003586

AIM fa perdere il 14.6% (un po' piu' di quanto AOW faceva perdere alla difesa centrale), LI il 7%

extraMulti = 1.000 # fixed

il solito residuo del passato

squareMod = 0.011591 # err=0.000943
cubeMod = -0.000029 # err=0.000003

quindi rating + 0.011591*rating*rating -0.000029*rating*rating*rating

pullback = 0.25



Infine ecco i Pesi in difesa e parate per i vari ruoli

[goalkeeping_allsides]
keeper = 0.61700

[defending_allsides]
keeper = 0.27650

[defending_thisside]
CD_norm = 0.49824
CD_off = 0.37680
CD_tw = 0.73200
WB_norm = 0.92250
WB_off = 0.65800
WB_def = 0.98000
WB_tm = 0.70600
IM_norm = 0.17388
IM_off = 0.09660
IM_def = 0.24932
IM_tw = 0.22954
WI_norm = 0.35000
WI_off = 0.18500
WI_def = 0.49800
WI_tm = 0.31250

[defending_middle]
CD_norm = 0.24960
CD_off = 0.18225
IM_norm = 0.08708
IM_off = 0.02563
IM_def = 0.12472




4 centralattack.dat

[general]
multiplier = 0.250000 # fixed
delta = 1.000000 # fixed

al solito, alla fine dovrò dividere per 4 e sommare 1

trainerOff = 1.135257 # err=0.004339
trainerDef = 0.927930 # err=0.005792
trainerNeutral = 1.050000 # fixed

+13.5% con l'allenatore offensivo, -7.2% col difensivo, +5% col normale

confidence = 0.0525 # Educated guess by GM-Mjoelnir :-)

valore della fiducia

extraMulti = 1.000 # fixed

il solito residuo del passato

squareMod = 0.011339 # err=0.001363
cubeMod = -0.000029 # err=0.000005

quindi rating + 0.011399*rating*rating -0.000029*rating*rating*rating

tacticLongshots = 0.970577 # err=0.008211

perdita del 3% del con la tattica tiri da lontano

pullback = -0.25


che è l'opposto del valore di difesa


Infine ecco i Pesi in attacco e passaggi per i vari ruoli

[scoring_allsides]
FW_norm = 0.56306
FW_def = 0.34310
FW_tw = 0.34310

[passing_allsides]
IM_norm = 0.17756
IM_off = 0.26404
IM_def = 0.11960
IM_tw = 0.12650
WI_norm = 0.06100
WI_off = 0.08000
WI_def = 0.03100
WI_tm = 0.08800
FW_norm = 0.20774
FW_def = 0.32195
FW_def.technical = 0.32195
FW_tw = 0.14664





5 sideattack.dat

[general]
multiplier = 0.250000 # fixed

delta = 1.000000 # fixed

al solito, alla fine dovrò dividere per 4 e sommare 1

trainerOff = 1.133359 # err=0.003514
trainerDef = 0.921278 # err=0.004323
trainerNeutral = 1.050000 # fixed

+13.3% con l'allenatore offensivo, -7.9% col difensivo, +5% col normale

confidence = 0.0525 # Educated guess by GM-Mjoelnir :-)

valore della fiducia

extraMulti = 1.000 # fixed

il solito residuo

squareMod = 0.012093 # err=0.001183
cubeMod = -0.000027 # err=0.000005

quindi rating + 0.012093*rating*rating -0.000027*rating*rating*rating

tacticLongshots = 0.972980 # err=0.006620

perdita del 2.7% del con la tattica tiri da lontano

pullback = -0.25


e infine

[passing_middle]
IM_norm = 0.08714
IM_off = 0.09067
IM_def = 0.05602

[passing_allsides]
FW_norm = 0.10011
FW_def = 0.18612
FW_def.technical = 0.27495

[winger_allsides]
FW_norm = 0.15181
FW_def = 0.10340

[passing_thisside]
IM_norm = 0.17434
IM_off = 0.18538
IM_def = 0.11224
IM_tw = 0.21712
WI_norm = 0.18200
WI_off = 0.20900
WI_def = 0.15000
WI_tm = 0.13500
FW_tw = 0.14805

[winger_thisside]
CD_tw = 0.21360
WB_norm = 0.43450
WB_off = 0.55000
WB_def = 0.27500
WB_tm = 0.24150
IM_tw = 0.39468
WI_norm = 0.73900
WI_off = 0.83250
WI_def = 0.62250
WI_tm = 0.54000
FW_tw = 0.33887

[scoring_allsides]
FW_norm = 0.18424
FW_def = 0.09400

[scoring_otherside]
FW_tw = 0.12757

[scoring_thisside]
FW_tw = 0.31255


PS. dai un occhio all' INDICE del blog, ci sono parecchi articoli che ti potrebbero interessare.




Andreac (team ID 1730726 in Hattrick)

Creative Commons License
This opera by Andreac is licensed under a Creative Commons Attribuzione-Non commerciale 3.0 Unported License. Cioé questo lavoro può essere liberamente copiato, distribuito o modificato senza espressa autorizzazione dell'autore, a patto che l'autore sia chiaramente indicato e la pubblicazione non sia a fini commerciali.

4 commenti:

Anonimo ha detto...

can you plz add english comments to you HO prediction... what is 253F_1dc_1terz for instance?

Andreac ha detto...

Hi there... it's pretty easy:

DC = difensore centrale (central defender)
TERZ = terzino (wing back)
CC = centrocampista centrale (inner midfielder)
ALA/ALI = ala (wing)
that's it

Anonimo ha detto...

thx...i admire your great work since changes last saison!

but if you have poor understanding of romanic language it isn't that easy;-)

Andreac ha detto...

I've started to translate here http://hattrickanalysis.blogspot.com/ but it's a pretty long work... :)