Fwd: Opening Training

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Fwd: Opening Training

Facil Sempre
 I have been using the SCID opening training extensively and while it is a useful utility, it can be improved. It seems that when it is the computer move, it chooses a random move without taking care of anything else. That is an easy way to get it running, but it turns out that it repeats the same positions a lot while others are totally ignored (just because is a random walk).

I do not know if there is a _right_ solution to this problem, but let me explain what I think could be best than what it is actually coded now.

The relevant code in opening.tcl is:

  ################################################################################
  # play one of the candidate moves
  ################################################################################
  proc play { cm } {
    # addStatsPrev -good 0 -dubious 0 -absent 0 -total 1
    set r [expr int(rand()*[llength $cm]/2) ]
    set m [ lindex $cm [ expr $r * 2 ] ]
   
    if {[sc_pos moveNumber] == 1 && [sc_pos side] == "white"} {
      ::game::Clear
    }
   
    if {![catch {sc_move addSan [::untrans $m] }]} {
    }
    updateBoard -pgn -animate
  }


I won't pretend I understand exactly what it does, but it seems pretty clear that it chooses a random move from the whole list.

I propose two options, one easy and one difficult. Both I think are far beyond my capability as a programmer, but I want to hear your opinion before even trying to do anything (hoping, I'm not going to lie to you) that someone picks the gauntlet and does it for me.

Easy option:

Each move has a counter of numbers of times played, how many times there have been a correct move and how many times there have been a bad move. So for each candidate move (cm) we will add the numbers of its children nodes (as it is a computer node, it cannot have bad moves per definition, so if we want to take that into account, and I think it is important, we need to do this trick), and that would be the computer node's 'times reached', 'good moves' and 'bad moves'.

For each node, we would do this weight:

cm.weight = 1/[(times reached+0.1 /* to avoid dividing by zero */) * (1-bad moves/times reached-0.001 /* to avoid dividing by zero */)]

That will make moves that has been played less often more frequent, and moves that have a higher percentage of mistake to be played more. However, it will not take into account that there are branches bigger than others, hence favoring simple lines over harder ones.

Difficult option:

We want to train the whole tree, and it is possible that a branch (1. e4 e5) is way larger than other branch (say 1.e4 Nc6). Hence the larger branch should be drawn a lot more than the small one.

So let's say cm is the list of candidate moves. I would add to each move in cm a number, which would be the number of nodes in the tree after that branch is played. Moreover, I would keep count of how many times those nodes have been reached and the number of bad moves played on those nodes, to have something like this after 1.e4:

* 1...e5: nodes after that move = 1000; number of times those nodes have been reached = 750; number of bad moves in those nodes = 150.
* 1...Nc6: nodes after that move = 100; number of times those nodes have been reached = 80; number of bad moves in those nodes = 5.

Now we have to weight both moves on account of this data. What I propose is to do this. We calculate this number for each move:

1/[(number of times nodes reached / total nodes) * (1-number of bad moves/number of times nodes reached)]

1...e5 -> 1/[750/1000*(1-150/750)]=1/0.6=1.666
1...Nc6 -> 1/[80/100*(1-5/80)]=1/0.75=1.333

So those are the weight of the moves. It will play moves that has less proportion of time reached vs total nodes (so we will get less seen positions more often) and it will play more times those nodes where we have higher percentage of mistakes.

Of course this is a formula I got but there should be plenty better than that.

We have to add to that a little hiccup: when there exists transpositions this will not work properly. Imagine our repertoire holds:

1.e4 e5 2.Nf3 Nc6 - 1000 positions.
1.e4 e5 2.Nf3 Nf6 - 100 positions
1.e4 e6 -1000 positions.
1.e4 Nc6 2.Nf3 something different than 2...e5 100 positions.

When choosing between 1...Nc6, 1...e5 and 1...e6, the first option actually has 1100 nodes, because of the transposition to 1...e5, the second has also 1100 options, and the third has 1000. Hence we would end up going for 1.e4 e5 2.Nf3 Nc6 twice as much as we need. A good solution would be to count each node only as a fraction





------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Scid-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/scid-users