---
title: "Train a text classifier in C#"
url: https://recursiveai.org/onenlp/cookbook/text-classification/
description: "Train a classifier to label text, using two tiny demonstration examples."
version: "1.0.0"
---

# Train a text classifier in C#

**OneNLP** is a free, open-source natural language processing library for .NET from Recursive AI. MIT or Apache-2.0, no native dependencies.

[NuGet](https://www.nuget.org/packages/RecursiveAI.OneNlp.Neural) · [GitHub](https://github.com/recursive-ai-oss/onenlp-csharp) · [Docs](https://recursiveai.org/onenlp/docs/) · [Download example (.zip)](https://recursiveai.org/onenlp/cookbook/text-classification/text-classification.zip)

Train a classifier to label text, using two tiny demonstration examples. This trains from zero, with no pretrained model, and nothing downloads at runtime.

```shell
dotnet add package RecursiveAI.OneNlp.Neural
```

Requires [.NET 10](https://dotnet.microsoft.com/download/dotnet/10.0) (net10.0); .NET 9 and earlier aren’t supported.

```csharp
using RecursiveAI.OneNlp;
using RecursiveAI.OneNlp.Neural.Components;
using RecursiveAI.OneNlp.Neural.Encoders;

using var pipeline =
    Pipeline.Blank(Language.English)
    .Add(new TextClassifier(
        FastEncoder.English(7))
        { OwnsEncoder = true });
Example[] examples = [
    Example.Create(
        pipeline, "hello", cats:
        new Dictionary<string, float>
        { ["greeting"] = 1 }),
    Example.Create(
        pipeline, "goodbye", cats:
        new Dictionary<string, float>
        { ["farewell"] = 1 })
];
pipeline.Train(examples, new TrainOptions
{ Epochs = 30, DevFraction = 0, Seed = 7 });
Doc doc = pipeline.Process("hello");
var best = doc.Cats.MaxBy(
    pair => pair.Value);
Console.WriteLine(best.Key);
```

```text
greeting
```

Unzip [the example](https://recursiveai.org/onenlp/cookbook/text-classification/text-classification.zip), then `dotnet run`.

## Full program

The program trains on two invented inputs: “hello” is a greeting and “goodbye” is a farewell. It then classifies “hello”. This deliberately small training example demonstrates the API, not accuracy on new messages. All inputs appear in `Program.cs`; there are no external files. In `FastEncoder.English(7)`, `7` is the random seed used to initialize the encoder’s weights, not a model version; `TrainOptions.Seed = 7` separately sets the training seed. NuGet restore downloads the library packages before the program runs.

The download’s `Program.cs` is the snippet above.

`dotnet run` prints:

```text
greeting
```

Malformed training annotations can throw `ArgumentException`; use the documented category format and scores between zero and one.

## Variations

**Read category scores.** After training, replace the final `Console.WriteLine` with this loop. `doc` is the analyzed document from the full program.

```csharp
foreach (var pair in doc.Cats.OrderByDescending(pair => pair.Value))
    Console.WriteLine(FormattableString.Invariant($"{pair.Key}: {pair.Value:F3}"));
```

```text
greeting: 1.000
farewell: 0.000
```

## Related recipes

- [Part-of-speech tagging in C#](https://recursiveai.org/onenlp/cookbook/part-of-speech-tagging/)
- [Dependency parsing in C#](https://recursiveai.org/onenlp/cookbook/dependency-parsing/)

## The short answer

To train a text classifier in C#, add `RecursiveAI.OneNlp.Neural`, create a blank pipeline, add a `TextClassifier`, and train it with labeled `Example` objects. Calling `Process` then puts category scores in `Doc.Cats`. The complete example above supplies every training input in code and prints the label with the highest score.

This is supervised classification: you define the labels and provide examples of them. It does not ask a hosted model to invent categories for arbitrary text. The [classification documentation](https://recursiveai.org/onenlp/docs/classification/) describes the classifier head and its category output, while the [training guide](https://recursiveai.org/onenlp/docs/training/) covers the training options.

## What is text classification?

Text classification assigns categories to whole documents. A document can be a short message rather than a page of prose. The classifier in this example chooses between a greeting and a farewell; a real application might classify support requests into its own routing categories.

Choose the category system before collecting the data. Labels should represent the decision you need to make, and each labeled example should follow the same definition. If annotators disagree about the distinction, collecting more examples without clarifying the labels will not resolve that ambiguity.

OneNLP’s classifier averages the encoder’s token vectors and applies a classification layer. The default is exclusive classification using a softmax: the scores across categories sum to one. The same API also supports multiple independent labels with `multiLabel: true`, which uses independent sigmoid scores instead. Pick the mode according to whether labels can coexist, not according to how many labels you have in total.

## What is an example of text classification?

The program uses “hello” and “goodbye” as two labeled training documents. `Example.Create` tokenizes them through the pipeline and attaches their category annotations. Missing category labels count as zero. The fixed seed makes the demonstration repeatable, and disabling the development split keeps both tiny examples in training.

It then predicts “hello”, one of the training inputs. That is useful for showing the API, but it says nothing about generalization. A classifier that remembers a training example may still fail on new greetings, misspellings or messages containing several intents. The high scores shown in the variation are not evidence of production accuracy.

For a real system, reserve examples that training never sees. Evaluate on the kinds of messages you expect after deployment, including borderline cases. Use the documented development-set options for model selection and a separate evaluation set for the final decision. This demonstration’s `DevFraction = 0` is a convenience for two invented inputs, not a recommendation for evaluating a real model.

## How do I build a text classification example in C#?

Start with the downloadable project and replace the examples with your own labeled messages. Keep the same tokenizer for training and prediction; using `Example.Create(pipeline, ...)` does that directly. For larger datasets, the library also accepts JSON Lines with a text field and category-score mapping, as described in [data formats](https://recursiveai.org/onenlp/docs/data-formats/).

Read all category scores when debugging instead of only the winning label. The variation sorts them for inspection. In a single-label classifier, a highest score still exists for an unfamiliar message, so selecting the maximum alone is not a rejection policy. Decide how to handle unsupported inputs using held-out examples from your application. Do not treat a score learned from this toy dataset as a calibrated probability for real-world traffic.
