Ultralytics YOLO27: Join the waitlist.
Get Started
Lessonbeginner

Start With the Business Objective

Turn a business goal into a vision task, defined classes, and an acceptance test you can run as code, before a single image is collected.

A desk with a laptop showing a labeled image dataset, sorted photo prints, class sticky notes and a dataset checklist

A warehouse team photographs everything for a month, then learns the safety lead only cares about people near moving forklifts, and half the labels must be redone. A one-page objective, agreed before the first photo, prevents that. It takes an afternoon and decides every later choice in this course: what to collect, what to label, and when the model is good enough to ship.

Outcome

Write a one-page objective and turn its success metric into an acceptance test script that prints PASS or FAIL for any model.

Fast Track
If you already know your way around, here's the short version.
  1. Write the business goal as one measurable sentence with a deadline.

  2. Pick the simplest of the seven vision tasks that answers it.

  3. Define 3–10 classes in one sentence each, naming a look-alike each one excludes.

  4. Write the acceptance test: metric, threshold, and an unseen holdout. Then run it as code.

  5. List what v1 will not handle.

Hands-on

The one-page objective#

Ultralytics YOLO task outputs side by side: detect, pose, segment, classify, OBB, semantic segmentation, and depth

Five rows answer the questions every later step depends on. The defining project goals guide covers the same ground in more depth. Here is a filled-in warehouse example, which this course builds on:

RowQuestion it answersWarehouse example
Business goalWhat changes for the business, and by when?Cut dock-door near-miss incidents by 30% within six months.
Vision taskWhat does the model output?Object detection: boxes around forklifts and people.
ClassesWhat exactly gets a label?forklift, person, pallet; everything else is background.
Acceptance testWhat number means "ship it"?Recall on person ≥ 0.95 at precision ≥ 0.85 on 500 frames from cameras not used in training.
Out of scopeWhat will v1 not promise?Pitch-dark docks, people fully hidden behind racks, hand pallet jacks.

Pin the page where the whole team can see it. If a stakeholder disputes a row later, change the page first and the dataset second.

Pick the simplest task that answers the question#

The same cat-and-dog scene answered three ways: image classification asks whether it is a cat, object detection asks what is where, and image segmentation asks which pixels belong to which object

The task decides what annotators draw, and that decides most of the labeling budget. Work down this decision tree and stop at the first task that answers the business question:

Ultralytics YOLO supports seven tasks. For dataset planning, what matters is what each one costs to label; Computer Vision Foundations compares them in depth in its vision tasks lesson.

TaskWhat annotators produceLabeling effortChoose it when
ClassificationOne label per imageLowestOne answer per image is enough
DetectionClass + axis-aligned box per objectLowYou need to count or locate objects
OBBClass + rotated box per objectMediumObjects are long, thin, or seen from above
PoseClass + named keypoints per objectHighJoint or part positions matter
Instance segmentationClass + polygon per objectHighThe outline of each object matters
Semantic segmentationA class for every pixelHighestYou need regions, not countable objects
Depth estimationNothing drawn: a depth map per image, usually from a depth sensorDepends on capture hardwareYou need distance at every pixel

Types of image annotation on a bunch of bananas: classification reveals presence, detection adds location and count, semantic segmentation shows which pixels are banana, and instance segmentation adds each banana's size and shape

Read the banana panel as a price list: detection already answers presence, location, and count, and only the two segmentation panels add size and shape, at a much higher labeling cost. If the business only needs "how many bananas", detection is the answer, and polygons are wasted budget.

Segmentation by default drains the budget

Teams often reach for segmentation because it looks more precise, then run out of labeling budget before the dataset covers night shifts, rain, or the second site. Polygons cost several times more per object than boxes. Choose segmentation only when a row of the objective needs the outline itself, such as measuring area or cutting a mask.

Write classes an annotator can apply#

A class is only useful if two annotators label the same object the same way. Write each one as a one-sentence definition that names a look-alike it excludes:

  • forklift: a powered lift truck, including its forks and mast. Excludes hand pallet jacks.
  • person: any human, including partly visible, seated, or inside a vehicle cab. Excludes reflections and posters.
  • pallet: a wooden or plastic shipping pallet, loaded or empty. Excludes stacked crates without a pallet base.

Then choose the granularity deliberately. Coarse classes ("vehicle") are cheaper and converge faster; fine classes ("sedan", "pickup") are more useful downstream but harder to keep consistent. Start with what the business needs. Fine labels can be merged into coarse ones later with one line of code, but coarse labels can never be split without relabeling.

If you can't write it down, annotators can't label it

"Anything that looks dangerous" or "stuff blocking the aisle" is not a class. It asks each annotator for a judgment call, and a model trained on inconsistent judgments learns the inconsistency. Rewrite a vague class until a new annotator could apply it from the definition alone, or turn it into a rule applied after detection (for example, "any pallet inside the aisle polygon").

Turn the metric into an acceptance test you can run#

Pick the metric that matches the cost of a mistake:

  • A miss is expensive (safety, defects): gate on recall for that class.
  • A false alarm is expensive (auto-rejecting parts, alerting staff): gate on precision.
  • Every class matters equally (counting, inventory): gate on per-class AP, so no class hides behind the average.

The YOLO performance metrics guide explains each one. Then write the test as code, so "is it good enough?" stops being a debate. This script runs today with a pretrained model on the COCO8 demo set, and later with your own checkpoint and holdout:

from ultralytics import YOLO

model = YOLO("yolo26n.pt")  # later: your fine-tuned runs/detect/train/weights/best.pt
metrics = model.val(data="coco8.yaml", classes=[0], verbose=False)  # 0 = person; later: your holdout YAML

precision, recall = metrics.box.mp, metrics.box.mr
print(f"person: precision={precision:.2f} recall={recall:.2f}")
print("PASS" if recall >= 0.95 and precision >= 0.85 else "FAIL: below the acceptance test")
                   all          4         10      0.939        0.8      0.848      0.387
person: precision=0.94 recall=0.80
FAIL: below the acceptance test

What each line tells you:

  • classes=[0] scores only person, so other classes cannot pad the result. Use your own safety class ID.
  • The validator row shows 4 images with 10 labeled people. mp and mr are precision and recall at the confidence threshold that balances them best (maximum F1).
  • A pretrained COCO model finds 8 of the 10 people, so recall is 0.80: precise, but not safe enough. That FAIL is the test doing its job. In this course, a FAIL leads back to the data, not to hyperparameters.
The holdout clause matters as much as the number

A test drawn from the same cameras and days as training measures memory, not readiness. Name the holdout in the objective ("cameras not used in training", "the last two weeks of footage"), and build it with Split the Dataset Correctly.

Write down what v1 won't do#

No model is perfect, so name the acceptable misses up front: conditions you won't promise (heavy fog, total darkness), look-alikes you'll tolerate confusing, and long-tail classes deferred to v2. This row keeps a model that meets its target from being judged against an unwritten 100% bar, and it tells the collection team where not to spend effort yet.

Try It

Fill in the five-row objective table for your own project and send it to the person who owns the business result. Revise every row they question. Then copy acceptance_test.py, set your class ID and thresholds, and run it against the pretrained model so the test exists before the dataset does. Deliverable: objective.md and a working acceptance_test.py.

Done When
You've finished the lesson when all of these are true.
  • The business goal is one measurable sentence with a deadline, and the owner has agreed to it.

  • Every class has a one-sentence definition and at least one named look-alike it excludes.

  • acceptance_test.py runs and prints PASS or FAIL for a metric, a threshold, and a named holdout.

Show solution

A worked objective for a different project, a grocery chain detecting empty shelf slots:

RowAnswer
Business goalCut out-of-stock minutes on the top 200 products by 25% within one quarter.
Vision taskDetection. The store needs the location of each gap, not its outline, so boxes beat polygons.
Classesgap: an empty shelf slot at least one product wide; excludes slots hidden by a shopper or cart. price_tag: a shelf-edge label; excludes promotional stickers.
Acceptance testRecall on gap ≥ 0.90 at precision ≥ 0.80 on 400 images from 5 stores not used in training.
Out of scopeFreezer doors with glare, end-cap displays, the produce section.

Recall comes first because a missed gap costs a sale, while a false alarm costs a staff member a short walk. acceptance_test.py changes in only three places: data="holdout_stores.yaml" (the five unseen stores), classes=[0] (0 is now gap), and the thresholds recall >= 0.90 and precision >= 0.80.

What's next

Next, turn the objective into a dataset specification that says which images you need and how many of each.