3: Data, part 2
March 8, 2025
Good one. Let’s talk about converting game transcripts to vectors!
Categorical Data
One thing I learned, from my time working with neural networks, is one-hot encoding. Let’s say you are trying to train a model to predict house prices. One feature (factor) you want to consider in your model is whether the residence is single-family, a townhouse, apartment, etc. Say every datapoint fits into one and only one of these categories. How can we represent this numerically? It might be easy to just start assigning IDs to each of these categories.
{
“single-family”: 0,
“townhouse”: 1,
“apartment”: 2,
…
}
Uh oh, problem! A neural network (the underlying structure we’re using for our model) will interpret this as numeric, akin to the degree to which a feature is (e.g. house age, which scales continuously). That’s a nono, because there is no relationship in the degree of category ID to the house price. Here’s what I mean:
You might expect the relationship between house price and house age to be a continuous function, like this.
But the relationship between house price and category index? Something piecewise like this.
Generally, a neural network doesn’t do so good with piecewise inputs. This is where we use one-hot encoding. Instead of inputting category ID as one dimension in our neural network model, we instead spread it out to n dimensions where n is the number of categories.
Suppose the category index is k. Then, the one-hot encoding we use for our neural network would be defined as
, where
Why is This Relevant?
If we recall what information we want to encode:
Hands: YS:{S9,CJ,H3,DK,SA,S2}
Asks: KZ PB H9 0
Calls: KZ KZ:{HJ,HQ,HK} OZ:{H9,HT,HA} 1
None of these are numeric. Players should be easy to represent, one-hot encoded into a vector of length 8. Cards, are a little trickier. We could use a vector of 54 dimensions, one for each card in the deck, but that would get very long very quickly, particularly when encoding calls when multiple cards are involved. Thankfully, we have the power of combinatorics. I’ve instead chosen to use a vector with 9 values to encode the card’s set, and another vector with 6 values to encode the card’s position in the set, according to the following array:
[
[“D2″,”D3″,”D4″,”D5″,”D6″,”D7”],
[“C2″,”C3″,”C4″,”C5″,”C6″,”C7”],
[“H2″,”H3″,”H4″,”H5″,”H6″,”H7”],
[“S2″,”S3″,”S4″,”S5″,”S6″,”S7”],
[“D9″,”DT”,”DJ”,”DQ”,”DK”,”DA”],
[“C9″,”CT”,”CJ”,”CQ”,”CK”,”CA”],
[“H9″,”HT”,”HJ”,”HQ”,”HK”,”HA”],
[“S9″,”ST”,”SJ”,”SQ”,”SK”,”SA”],
[“D8″,”C8″,”H8″,”S8″,”*S”,”*B”]
]
This way, we only really need a vector with 15 dimensions to encode 9×6=54 different possibilities. By combining these pieces of information, we can convert any game into a state of 200×54, where 200 is the number of actions that any player take in an entire game (which is typically 100-120, but given 80 extra rows for backup) and 54 is the encoding for each action.
Next time, let’s talk about the neural network I’ve been working on!
Leave a Reply
You must be logged in to post a comment.