TensorFlow
CSV Reader
Machine Learning
Data Processing
Python

What am I missing from this csv reader for TensorFlow?

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Common issues with TensorFlow CSV readers stem from incorrect column types, missing default values, header row handling, and mismatched feature columns. TensorFlow's tf.data.experimental.make_csv_dataset and tf.data.experimental.CsvDataset expect precise column specifications. The most frequent mistake is not providing column_defaults that match the CSV's actual data types, causing silent parsing failures or InvalidArgumentError. The modern approach uses tf.data.experimental.make_csv_dataset which handles most configuration automatically.

Basic CSV Reading with tf.data

python
1import tensorflow as tf
2
3# Method 1: make_csv_dataset (recommended — handles most details)
4dataset = tf.data.experimental.make_csv_dataset(
5    "data.csv",
6    batch_size=32,
7    label_name="target",        # Column to use as label
8    num_epochs=1,               # How many times to read the file
9    shuffle=True,
10    ignore_errors=True          # Skip malformed rows
11)
12
13# Each element is (OrderedDict of features, label tensor)
14for features, label in dataset.take(1):
15    print(features)
16    print(label)

Common Issue 1: Missing column_defaults

python
1# CSV file: id,name,score,passed
2# 1,Alice,95.5,true
3# 2,Bob,87.0,false
4
5# WRONG — no defaults, TF cannot infer types
6dataset = tf.data.experimental.CsvDataset(
7    "data.csv",
8    record_defaults=[],  # Empty — causes error
9    header=True
10)
11
12# RIGHT — provide a default for each column with the correct type
13dataset = tf.data.experimental.CsvDataset(
14    "data.csv",
15    record_defaults=[
16        tf.constant(0, dtype=tf.int32),      # id (int)
17        tf.constant("", dtype=tf.string),     # name (string)
18        tf.constant(0.0, dtype=tf.float32),   # score (float)
19        tf.constant("", dtype=tf.string)      # passed (string — bool not supported directly)
20    ],
21    header=True
22)
23
24for row in dataset.take(2):
25    print(row)

record_defaults tells TensorFlow the type of each column AND what value to use if a field is empty. The number of defaults must match the number of columns.

Common Issue 2: Header Row Parsed as Data

python
1# WRONG — header=False (default) treats the first row as data
2dataset = tf.data.experimental.CsvDataset(
3    "data.csv",
4    record_defaults=[tf.constant(""), tf.constant("")],
5    # header=False is the default — first row "name,score" becomes data
6)
7
8# RIGHT — skip the header row
9dataset = tf.data.experimental.CsvDataset(
10    "data.csv",
11    record_defaults=[tf.constant(""), tf.constant(0.0)],
12    header=True  # Skip the first line
13)

Common Issue 3: Type Mismatch

python
1# CSV has: "95.5" but you declared int default
2# record_defaults=[tf.constant(0)]  # int32 — fails on "95.5"
3
4# Fix: use float default for decimal values
5record_defaults = [tf.constant(0.0)]  # float32
6
7# Or let make_csv_dataset infer types
8dataset = tf.data.experimental.make_csv_dataset(
9    "data.csv",
10    batch_size=32,
11    column_defaults=[0, "", 0.0, ""],  # Python types work too
12    label_name="target"
13)

If a column contains 95.5 but the default is tf.int32, TensorFlow raises InvalidArgumentError: Field 2 in record is not a valid int32.

Common Issue 4: Selecting Specific Columns

python
1# Only read certain columns (skip others)
2dataset = tf.data.experimental.CsvDataset(
3    "data.csv",
4    record_defaults=[tf.constant(0.0), tf.constant(0.0)],
5    header=True,
6    select_cols=[2, 3]  # Only read columns at index 2 and 3
7)
8
9# With make_csv_dataset — use select_columns by name
10dataset = tf.data.experimental.make_csv_dataset(
11    "data.csv",
12    batch_size=32,
13    select_columns=["score", "target"],  # Column names from header
14    label_name="target"
15)

Common Issue 5: Missing Values

python
1# CSV with missing values:
2# 1,Alice,95.5
3# 2,Bob,
4# 3,,87.0
5
6# Provide meaningful defaults for missing values
7dataset = tf.data.experimental.CsvDataset(
8    "data.csv",
9    record_defaults=[
10        tf.constant(0, dtype=tf.int32),
11        tf.constant("Unknown", dtype=tf.string),  # Default for missing names
12        tf.constant(0.0, dtype=tf.float32)          # Default for missing scores
13    ],
14    header=True
15)

Empty fields are replaced with the corresponding default value. If no default is provided and a field is empty, TensorFlow raises an error.

Building a Complete Input Pipeline

python
1import tensorflow as tf
2
3def build_csv_pipeline(file_pattern, batch_size=32, label_col="target"):
4    # Read all CSV files matching the pattern
5    dataset = tf.data.experimental.make_csv_dataset(
6        file_pattern,
7        batch_size=batch_size,
8        label_name=label_col,
9        num_epochs=1,
10        shuffle=True,
11        shuffle_buffer_size=10000,
12        prefetch_buffer_size=tf.data.AUTOTUNE,
13        num_parallel_reads=tf.data.AUTOTUNE,
14        ignore_errors=True
15    )
16
17    # Preprocessing
18    def preprocess(features, label):
19        # Normalize numeric features
20        features["score"] = (features["score"] - 50.0) / 50.0
21        return features, label
22
23    dataset = dataset.map(preprocess, num_parallel_calls=tf.data.AUTOTUNE)
24    dataset = dataset.prefetch(tf.data.AUTOTUNE)
25
26    return dataset
27
28# Usage
29train_ds = build_csv_pipeline("data/train_*.csv")
30model.fit(train_ds, epochs=10)

Using pandas as an Alternative

python
1import pandas as pd
2import tensorflow as tf
3
4# For smaller datasets, pandas is simpler
5df = pd.read_csv("data.csv")
6
7# Convert to tf.data.Dataset
8features = df.drop("target", axis=1)
9labels = df["target"]
10
11dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))
12dataset = dataset.shuffle(len(df)).batch(32).prefetch(tf.data.AUTOTUNE)

For datasets that fit in memory, loading with pandas first avoids the complexity of TensorFlow's CSV API.

Debugging CSV Reading Issues

python
1# Print the first few records to verify parsing
2dataset = tf.data.experimental.make_csv_dataset("data.csv", batch_size=1, num_epochs=1)
3
4for batch in dataset.take(3):
5    features, label = batch if isinstance(batch, tuple) else (batch, None)
6    for key, value in features.items():
7        print(f"{key}: {value.numpy()}")
8    if label is not None:
9        print(f"label: {label.numpy()}")
10    print("---")

Common Pitfalls

  • Wrong number of record_defaults: The number of defaults must exactly match the number of columns in the CSV. If the CSV has 5 columns but you provide 4 defaults, you get a cryptic error about record format.
  • Forgetting header=True: The default is header=False. If your CSV has a header row and you do not set this, the header becomes the first data record, causing type errors (e.g., parsing "score" as a float).
  • Field delimiter mismatch: The default delimiter is comma. For tab-separated files, set field_delim="\t". For semicolons (common in European CSVs), use field_delim=";".
  • Quoted fields with commas: CSV values containing commas must be quoted ("New York, NY"). TensorFlow's CSV reader handles standard quoting, but non-standard escaping (backslash instead of double-quote) causes parse failures.
  • Using CsvDataset when make_csv_dataset is simpler: CsvDataset requires manual batching, shuffling, and type specification. make_csv_dataset handles all of this automatically and should be the default choice for most use cases.

Summary

  • Use tf.data.experimental.make_csv_dataset for most CSV reading — it handles headers, types, batching, and shuffling automatically
  • Always provide record_defaults with the correct types when using CsvDataset
  • Set header=True if your CSV has a header row
  • Use select_columns (by name) or select_cols (by index) to read only needed columns
  • Use ignore_errors=True to skip malformed rows instead of crashing
  • For small datasets, loading with pandas and converting to tf.data.Dataset is simpler

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.