TensorFlow
CSV Reader
Machine Learning
Data Processing
Python

What am I missing from this csv reader for TensorFlow?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

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

Course illustration
Course illustration

All Rights Reserved.