Thursday, March 28, 2013

Corrections, Part 4: Methods and things

In my previous post, I showed a few plots representing the effect on movement and velocity only of applying a linear-operator-as-park-corrector to "correct" one game in Tampa to one game in Baltimore. This operator showed some improvement, but also created at least one more problem.  Specifically, it overcorrected the horizontal movement of Jeremy Hellicksons curveball to be much less than it should have been.  In that post, I went into almost no detail about how this operator was derived.  That's what this post is for.

The details so far are as follows (and note that there are many here that may change in the future).  The goal is to derive one operator that can be applied to positions, velocites and accelerations.  At this point, I apply that operator somewhere along the pitch trajectory, then propagate the pitch backwards to 55 ft to get the initial velocity and release parameters.  That's the plan for the use of this operator.

Recall in my first post the form I used to write down what we wind up seeing from PITCHf/x at any two given parks:

With p0 representing an identical pitch as it leaves the hand of a given player at either stadium S or stadium T.  The GRG^-1 term represents the correction term that must be applied to account for a difference in air density, with the R operator being a diagonal matrix with rho/rho_0 on the diagonal elements that correspond to ax, ay, and az, and rho represents the air density at that particular park, and rho_0 our standard air density.  T and S simply represent the operator that transforms an actual pitch that was thrown into the data we receive at their respective stadiums, and are unknown, and dt and ds are simply the data we receive.

Since the first toy experiment was designed to ignore the effects of air density, we can simplify to write:
dt = T p0
ds = S p0

If then we have a situation where the same pitch is recorded by our two different systems, T and S, then we can say:

p0 = T^-1 dt
and thus
ds = S T^-1 dt

Since both S and T are unknown, we can only solve for the combination S T^-1, or T S^-1 explicitly.  We'll call S T^-1 = A.  This A is the operator I am solving for in my toy experiment.

Now we simply assume that fastballs thrown by a given pitcher in one park are equivalent to fastballs he threw in the other park.  And the same for changeups, curves, etc, etc.  There are a few ways to approach this.  For now, I simply went with the brute force approach.  We "assume" that each pitch in a category thrown at one park maps exactly to each pitch in the same category thrown at the other park. (This actually works out to be nearly identical to using averages of the parameters, but with a weighting that prefers larger clusters, and although it seems like it should, it does not significantly add to computational complexity).  Doing so gives a set of equations of the following form for each mapping defined

a11*xs + a12*ys + a13*zs = xt
a21*xs + a22*ys + a23*zs = yt
a31*xs + a32*ys + a33*zs = zt

where xs, ys, zs can represent acceleration components for pitches thrown in S and similar for pitches thrown in T.  Note though: We could also use velocities.  And release points.  Also note, in the case of accelerations, it turns out that when we cannot ignore air density, there is a 4th translation term in those equations, and it is proportional to the difference in air density between the two parks...but since we are ignoring air density for the time being, that term has been dropped.  You'll also note here that I have left out any scale factors.  For the moment, I am limiting myself to affine transformations without translations.

Next we just rewrite this set of 3 equations for each pitch mapping in matrix form.

Xa = y

where X is a 3N x 9 matrix (N here represents the number of pitch mappings we have, not the number of pitches thrown in each park.  In my toy model I have something like 5000 mappings) composed of pitch parameters for each pitch thrown in park T (Tampa in my previous post) and y is a 3N vector composed of pitch parameters for each pitch thrown in park S (Baltimore in my previous post), and a is a vector composed of the elements of A.  This is the classic inverse problem with the well known least squares solution of:
a = (X^T X)^-1 X^T b
(although computing this without loss of precision can be a bit of a headache, but there are ways around that)

Now, my first rounds of doing this were remarkably unstable.  So to stabilize things, I also included in X and y the initial velocity components of the pitch, and the results of that produced the movement plots you saw in the previous post.  As it was late when I got around to making plots, I didn't check the release points, or I would have shown you how bad they got screwed up.  The separation in release points got bigger.  In my tests so far today, I included release point data, and that seemed to fix the release points, but also let a little bit of the original movement separation back in.  However it's progress.  I should also note that the matricies looked almost the way I thought they might look.  More like a shear mapping than anything else.  Imagine the x/y plane staying mostly fixed and the z axis falling over a little bit in some direction.  Also, this was not a large tilt by any stretch of the imagination.  About 6 degrees.  It's hard to notice a picture frame thats off by 6 degrees.

So anyway, that's where all this is at right now.  It's not as pretty as I hoped, and I'm not showing plots now because I don't feel like wasting space with them, but it's not a complete loss yet.  (If you'd like to see more plots, just let me know.  I may make a big plots post.  I've got about a million of them now.) I may have to open things up and compare more than just two games.  Two series maybe.  We'll see.  I may also need to open it up to the possibility of a projective transformation on the coordinate system.  I hope not though.  There's still more to try, and I'm encouraged that at least a few things are starting to converge.


Alan Nathan said...

Ike...I can sort of follow what you are doing. However, your notation is a bit clumsy, as your use of html tags. It makes it difficult to follow. Let me see if I can state things myself and you can tell me if you agree:

We want to find transformation A that takes x into y, where x is the 3xN matrix of accelerations for N pitches in stadium X and y is the same for stadium Y. A is a 3x3 matrix, so there are nine numbers for you to determine by solving the set of linear equations. One technique for solving the equations is Singular Value Decomposition (SVD). I'm sure you know the technique, but if not you can read about it in Numerical Recipes and other places.

Now, if you include position, velocity, and acceleration in the transformation, then x and y are 9xN matrices and A is a 9x9 matrix. To find 81 numbers, you will need at least 81 equations, meaning 81 pitches. Perhaps you can eliminate off-diagonal terms connecting "unlike" quantities (e.g., accelerations with velocities).

Am I on the right track?

Alan Nathan said...'s getting late. Let me take back what I said. To get 81 equations, you only need 9 pitches.

Isaac Hall said...

Sorry about the mathtype program was unavailable when I wrote the bulk of this...

So the inversion process is still trying to find a 3x3 matrix, as I am going to apply that same matrix to the positions, velocities, and accelerations. The process of applying the matrix treats it as a 9x9, but a block diagonal 9x9 with the same 3x3 in each block.

So in order to turn the problem of Ax = b where A is 3x3 (or 9x9 block-diagonal) and x and b are my data vectors into something I can actually solve, I instead turn A into a vector "a" and X into a big 3N x 9 (although I later grew it to 9Nx9 with the additions of velocities and positions) matrix, and b is just a column vector of the appropriate pitch parameters of each pitch mapping at the other park.

I should probably write out the form of X and b...

(non-fixed width fonts might screw this up)
X = [[ x y z 0 0 0 0 0 0 ]
[ 0 0 0 x y z 0 0 0 ]
[ 0 0 0 0 0 0 x y z ]
[vx vy vz 0 0 0 0 0 0 ]
[ 0 0 0 vx vy vz 0 0 0 ]
[ 0 0 0 0 0 0 vx vy vz]
[ax ay az 0 0 0 0 0 0]
[ 0 0 0 ax ay az 0 0 0]
[ 0 0 0 0 0 0 ax ay az]

Thats for one data point, at one park (the park we are transforming from. Further data points just get added below. the b vector is just the column vector of pitch parameters for the pitch being matched to at the other park, and the 'a' vector is the column vector [a11 a12 a13 a21 a22 a23 a31 a32 a33].

Does that help?

Alan Nathan said...

I think I have the essential idea of what you are doing, but I still have some questions and one suggestion. No time now to go further but I'll get back here later today.