← Back to list

Can Strokes Gained Predict Making a PGA Cut? A Graph Neural Network Approach

By Timothy Ross

Timothyross in ML4GClemson : Machine Learning for Graphs · 2026-05-01 17:17 · 55 claps · 5.1 min read
#machine-learning #gnn #ai #golf #sports-analytics
Open on Medium ↗
Wiki topics: ML · Machine Learning AI · AI · General EDU · Education & Learning GRW · Growth & Analytics 🏆 · Sports · General

Can Strokes Gained Predict Making a PGA Cut? A Graph Neural Network Approach

By Timothy Ross

Motivation

Each week on the PGA Tour, players and their teams must make a critical decision: whether entering a specific tournament is likely to be beneficial. This decision has direct implications for earnings, FedEx Cup points, and long-term competitive positioning. Traditionally, these choices are guided by a combination of intuition, course familiarity, and recent performance.

With the availability of advanced performance metrics, particularly strokes gained statistics, it becomes natural to ask whether this decision can be approached more systematically. Specifically, this project investigates whether historical strokes gained data can be used to predict whether a player will make the cut at a given tournament. More importantly, it explores whether modeling the PGA Tour as a relational system using Graph Neural Networks can improve predictive performance beyond traditional methods.

Dataset and Problem Setup

This study uses a publicly available dataset containing PGA Tour results across multiple seasons. Each observation represents a player’s participation in a specific tournament and includes player identifiers, tournament identifiers, tournament characteristics, and detailed strokes gained metrics. The strokes gained variables include putting, approach, around-the-green, off-the-tee, and total strokes gained.

To ensure that the model reflects a realistic decision-making scenario, features are constructed using only information that would be available prior to the tournament. Specifically, rolling averages of strokes gained metrics over a player’s previous ten tournaments are used to represent recent form.

The prediction task is formulated as a binary classification problem. The goal is to predict whether a player will make the cut at a given tournament. This framing aligns naturally with the underlying decision problem faced by players and their teams.

Baseline Models

Before introducing graph-based models, standard tabular approaches are used to establish baseline performance. A Random Forest classifier and a Multilayer Perceptron are trained using the engineered rolling features and tournament-level attributes.

Both models achieve moderate performance, with accuracy in the range of approximately 58 to 59 percent and ROC-AUC values around 0.60 to 0.61. These results indicate that strokes gained metrics do contain meaningful predictive signal. However, the performance also suggests that treating each player–tournament observation independently limits the model’s ability to capture more complex patterns.

Graph-Based Modeling

Professional golf is inherently relational. Players compete in overlapping fields, tournaments favor different skill profiles, and performance patterns often extend across similar players and events. These relationships are not explicitly modeled in traditional tabular approaches.

To address this limitation, the dataset is represented as a bipartite graph. One set of nodes corresponds to players, while the other corresponds to tournaments. An edge connects a player to a tournament if the player participated in that event. Each edge is labeled according to whether the player made the cut.

This graph representation allows information to propagate between related players and tournaments. For example, players who frequently appear in similar tournaments can influence each other’s representations, and tournaments that attract similar fields can develop shared characteristics.

Graph Neural Network Models

Two Graph Neural Network architectures are implemented using PyTorch Geometric.

The first model is GraphSAGE, which learns node embeddings by aggregating information from neighboring nodes. In this context, player embeddings are updated based on the tournaments they have participated in, and tournament embeddings are updated based on the players in their field.

class HeteroGraphSAGE(nn.Module):
    def __init__(self, hidden_channels):
        super().__init__()

        self.conv1 = HeteroConv({
            ('player', 'played_in', 'tournament'): SAGEConv((-1, -1), hidden_channels),
            ('tournament', 'rev_played_in', 'player'): SAGEConv((-1, -1), hidden_channels),
        }, aggr='sum')

        self.conv2 = HeteroConv({
            ('player', 'played_in', 'tournament'): SAGEConv((-1, -1), hidden_channels),
            ('tournament', 'rev_played_in', 'player'): SAGEConv((-1, -1), hidden_channels),
        }, aggr='sum')

        self.lin1 = nn.Linear(hidden_channels * 2, hidden_channels)
        self.lin2 = nn.Linear(hidden_channels, 1)

    def encode(self, data):
        x_dict = self.conv1(data.x_dict, data.edge_index_dict)
        x_dict = {key: x.relu() for key, x in x_dict.items()}
        x_dict = self.conv2(x_dict, data.edge_index_dict)
        return x_dict

    def decode(self, z_dict, edge_label_index):
        player_z = z_dict['player'][edge_label_index[0]]
        tournament_z = z_dict['tournament'][edge_label_index[1]]

        z = torch.cat([player_z, tournament_z], dim=-1)
        z = self.lin1(z).relu()
        z = self.lin2(z).view(-1)

        return z

    def forward(self, data, edge_label_index):
        z_dict = self.encode(data)
        return self.decode(z_dict, edge_label_index)

model = HeteroGraphSAGE(hidden_channels=64)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)

The second model is a Graph Attention Network. This model extends the aggregation process by assigning learned attention weights to neighboring nodes, allowing the model to focus on more informative relationships.

class HeteroGAT(nn.Module):
    def __init__(self, hidden_channels):
        super().__init__()

        self.conv1 = HeteroConv({
            ('player', 'played_in', 'tournament'): GATConv((-1, -1), hidden_channels, heads=2, concat=False, add_self_loops=False),
            ('tournament', 'rev_played_in', 'player'): GATConv((-1, -1), hidden_channels, heads=2, concat=False, add_self_loops=False),
        }, aggr='sum')

        self.conv2 = HeteroConv({
            ('player', 'played_in', 'tournament'): GATConv((-1, -1), hidden_channels, heads=2, concat=False, add_self_loops=False),
            ('tournament', 'rev_played_in', 'player'): GATConv((-1, -1), hidden_channels, heads=2, concat=False, add_self_loops=False),
        }, aggr='sum')

        self.lin1 = nn.Linear(hidden_channels * 2, hidden_channels)
        self.lin2 = nn.Linear(hidden_channels, 1)

    def encode(self, data):
        x_dict = self.conv1(data.x_dict, data.edge_index_dict)
        x_dict = {key: x.relu() for key, x in x_dict.items()}
        x_dict = self.conv2(x_dict, data.edge_index_dict)
        return x_dict

    def decode(self, z_dict, edge_label_index):
        player_z = z_dict['player'][edge_label_index[0]]
        tournament_z = z_dict['tournament'][edge_label_index[1]]

        z = torch.cat([player_z, tournament_z], dim=-1)
        z = self.lin1(z).relu()
        z = self.lin2(z).view(-1)
        return z

    def forward(self, data, edge_label_index):
        z_dict = self.encode(data)
        return self.decode(z_dict, edge_label_index)

gat_model = HeteroGAT(hidden_channels=64)
gat_optimizer = torch.optim.Adam(gat_model.parameters(), lr=0.001, weight_decay=1e-4)

Both models perform edge classification by combining the learned embeddings of players and tournaments to predict the probability that a player will make the cut.

Results

The GraphSAGE model achieves accuracy comparable to the baseline models, but with an improvement in ROC-AUC, reaching approximately 0.64 on the test set. This indicates that the model is better at ranking player–tournament pairs by likelihood of success, even if classification accuracy remains similar.

The Graph Attention Network produces slightly lower performance than GraphSAGE, with a test ROC-AUC of approximately 0.61. This suggests that, in this setting, the additional flexibility of attention mechanisms does not translate into improved predictive performance.

Across all models, a consistent pattern emerges: high recall for players who make the cut and low recall for those who miss it. This reflects both class imbalance and the inherent difficulty of predicting underperformance.

Discussion

The results demonstrate that strokes gained metrics do provide meaningful predictive power for cut-making outcomes. More importantly, incorporating relational structure through graph-based modeling improves the model’s ability to rank outcomes, which is particularly relevant for decision-making applications.

The graph representation enables the model to learn implicit notions of player–tournament compatibility. For instance, certain types of players may consistently perform well at tournaments with specific characteristics, and these patterns can be captured through message passing.

At the same time, the overall performance indicates that the problem remains challenging. Predicting missed cuts is particularly difficult, and the model tends to favor the majority class. This highlights the importance of further work in feature engineering, class balancing, and threshold selection.

Conclusion

This project demonstrates that strokes gained statistics can be used to predict whether a player will make the cut, and that Graph Neural Networks provide a meaningful improvement over traditional tabular models in capturing relational structure. While accuracy gains are modest, improvements in ranking performance suggest that GNNs offer a more nuanced understanding of player–tournament interactions.

From a practical perspective, the model can be interpreted as a decision support tool. Rather than making binary predictions, it provides probabilities that can inform tournament entry decisions. This aligns closely with how such a system would be used in real-world settings.

Future work could extend this approach by incorporating additional features, improving tournament representations, and refining the graph structure. Overall, the results support the use of graph-based methods as a promising direction for sports analytics and performance forecasting.

Resources

Data File: https://www.kaggle.com/code/aashidutt3/eda-pga-tour-golf-data


메타데이터
post_id
4e1db8710d22
slug
can-strokes-gained-predict-making-a-pga-cut-a-graph-neural-network-approach-4e1db8710d22
url
https://medium.com/ml4gclemson/can-strokes-gained-predict-making-a-pga-cut-a-graph-neural-network-approach-4e1db8710d22
canonical_url
https://medium.com/ml4gclemson/can-strokes-gained-predict-making-a-pga-cut-a-graph-neural-network-approach-4e1db8710d22
author_url
https://medium.com/@timothyross104
status
ok
fetched_at
2026-06-11 06:59:45