# sublabel for NER

**URL:** <https://support.prodi.gy/t/sublabel-for-ner/4223>\
**Category:** Uncategorized\
**Tags:** usage, ner, medical\
**Created:** [May 13, 2021, 12:26am UTC](https://support.prodi.gy/t/sublabel-for-ner/4223 "2021-05-13T00:26:36Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![tiktok](https://avatars.discourse-cdn.com/v4/letter/t/e56c9b/32.png) [@tiktok](https://support.prodi.gy/u/tiktok)\
**Post date:** [May 13, 2021, 12:26am UTC](https://support.prodi.gy/t/sublabel-for-ner/4223/1 "2021-05-13T00:26:36Z")

</div>

How could I annotate an Entity that has multiple attributes in prodigy - for example in a sentence - Patient did not complain of wheezing

in this case the:  
DiseaseEntity=wheezing  
Polarity=Negative

This is how it is represented in uima  
\<textsem:DiseaseAnnotation xmi:id="36944" sofa="1" begin="9747" end="9752" polarity="0" uncertainty="0" conditional="false" generic="false" historyOf="0" FocusText="wheezing" Scope="[PREN]"/\>

---

<div class="post-metadata">

**Author:** ![ines](https://sea2.discourse-cdn.com/flex020/user_avatar/support.prodi.gy/ines/32/3_2.png) [@ines](https://support.prodi.gy/u/ines)\
**Post date:** [May 14, 2021, 10:31am UTC](https://support.prodi.gy/t/sublabel-for-ner/4223/2 "2021-05-14T10:31:50Z")

</div>

Hi! The NER interface is really optimised for actual named entity recognition tasks where the goal is to predict single token-based tags. One option would be to make two passes over the data and use the first pass to focus on getting the boundaries right (e.g. `DiseaseEntity`) and then annotate all additional attributes in the next round (e.g. using a multiple choice interface). If you're doing two passes, you can also use the first round to make sure all entities are labelled and that the annotation scheme is implemented correctly, before going deeper.

I've also seen approaches that designed a very similar annotation task as a relation annotation task (maybe that was somewhere in the [`medical` tag](https://support.prodi.gy/tag/medical)) – but I think in that case, the goal was to also capture the indicator for the polarity (i.e. "not"). If that's not so important for you, that might be overkill.

---

<div class="post-metadata">

**Author:** ![tiktok](https://avatars.discourse-cdn.com/v4/letter/t/e56c9b/32.png) [@tiktok](https://support.prodi.gy/u/tiktok)\
**Post date:** [May 14, 2021, 1:31pm UTC](https://support.prodi.gy/t/sublabel-for-ner/4223/3 "2021-05-14T13:31:13Z")

</div>

multiple choice interface make sense - but could walk me through on how to use this interface?

---

<div class="post-metadata">

**Author:** ![tiktok](https://avatars.discourse-cdn.com/v4/letter/t/e56c9b/32.png) [@tiktok](https://support.prodi.gy/u/tiktok)\
**Post date:** [May 14, 2021, 1:42pm UTC](https://support.prodi.gy/t/sublabel-for-ner/4223/4 "2021-05-14T13:42:39Z")

</div>

prodigy ner.manual ner\_2 ./exported\_file.jsonl --view-id choice

usage: prodigy ner.manual [-h] [-lo None] [-l None] [-pt None] [-e None] [-C] dataset spacy\_model source  
prodigy ner.manual: error: unrecognized arguments: --view-id

---

<div class="post-metadata">

**Author:** ![ines](https://sea2.discourse-cdn.com/flex020/user_avatar/support.prodi.gy/ines/32/3_2.png) [@ines](https://support.prodi.gy/u/ines)\
**Post date:** [May 15, 2021, 1:48am UTC](https://support.prodi.gy/t/sublabel-for-ner/4223/5 "2021-05-15T01:48:13Z")

</div>

Hi! Sorry if the way I phrased this was a bit confusing – the idea I suggested was to start by labelling the entities with the top-level label (e.g. `Disease`) using `ner.manual`. In the next step, you could then load the existing dataset into a different recipe that uses the multiple choice UI and goes through every single entity and asks you to annotate additional labels.

For example, your custom recipe could look something like this. You can read more about custom recipes and how they work here: [https://prodi.gy/docs/custom-recipes](https://prodi.gy/docs/custom-recipes)

```python
import prodigy
from prodigy.components.db import connect
import copy

@prodigy.recipe("entity-sublabels")
def entity_sublabels(dataset, source_dataset):
    db = connect()
    stream = db.get_dataset(source_dataset) # load the existing NER annotations
    # The multiple choice options to add: you can set them up however you like
    options = [
        {"id": "Polarity=Positive", "text": "Polarity: positive"},
        {"id": "Polarity=Negative", "text": "Polarity: negative"}
    ]
    
    def get_stream(stream):
        for eg in stream:
            for span in eg.get("spans", []):
                # Create a new example for each annotated span and add choice options
                task = copy.deepcopy(eg)
                task["spans"] = [span]
                task["options"] = options
                yield task

    stream = get_stream(stream)

    return {
        "dataset": dataset, # dataset to save annotations to
        "view_id": "choice",
        "stream": stream
    }

```

You can run it with `prodigy entity-sublabels your_final_dataset your_ner_dataset -F recipe.py`, where `recipe.py` is the file containing the code.

There are various things you can add to make the process more efficient: for example, a good trick is to group the same entities together, so you can annotate all instances of "wheezing" in a row. Sorting by frequency is a nice trick as well, because you'll likely have an uneven distribution of entities, with some being super common and others being quite rare.

---

<div class="post-metadata">

**Author:** ![tiktok](https://avatars.discourse-cdn.com/v4/letter/t/e56c9b/32.png) [@tiktok](https://support.prodi.gy/u/tiktok)\
**Post date:** [May 16, 2021, 5:59pm UTC](https://support.prodi.gy/t/sublabel-for-ner/4223/6 "2021-05-16T17:59:39Z")

</div>

> [@ines](#):
>
> custom recipe could look something like this. You can read more about custom recipes and how they work her

Thank you

---

<div class="post-metadata">

**Author:** ![c00lcoder](https://sea2.discourse-cdn.com/flex020/user_avatar/support.prodi.gy/c00lcoder/32/2426_2.png) [@c00lcoder](https://support.prodi.gy/u/c00lcoder)\
**Post date:** [December 29, 2022, 2:34pm UTC](https://support.prodi.gy/t/sublabel-for-ner/4223/7 "2022-12-29T14:34:19Z")

</div>

Hi

I tried to implement this is prodigy and the choice options loaded and I was able to make selections; however, it isn't linked to the top-level label. Any idea of how it be remain linked to the top level label? Also, if there is more than one person, the script only loads one person per image, not all of them. Any guidance would be appreciated

```python
        for eg in stream:
            for span in eg.get("spans", []):
                if span["label"] == "person":
                    task = copy.deepcopy(eg)
                    task['spans'] = [span]
                    task['options'] = options
            # eg["options"] = options
                yield task  

```

Here is an example of the spans for one image

```python
"spans": [
{"label": "person", "model": "yolov3-opencv", "box": [409, 13, 360, 653], "points": [[409, 13], [769, 13], [769, 666], [409, 666]], "confidence": 0.9993869662284851, "color": "#ff00ff", "qid": "1_person", "person_filters_yolo": [0, 1]}, 
{"label": "person", "model": "yolov3-opencv", "box": [131, 147, 293, 515], "points": [[131, 147], [424, 147], [424, 662], [131, 662]], "confidence": 0.9951488375663757, "color": "#ff00ff", "qid": "2_person", "person_filters_yolo": [0, 1]}, 
{"label": "person", "probability": 0.9997418522834778, "box": [149, 153, 256, 506], "points": [[149, 153], [405, 153], [405, 659], [149, 659]], "model": "facebook/detr-resnet-50", "color": "#ffff00", "qid": "61_person", "person_filters": [61, 98], "person_number": "person_0"}, 
{"label": "person", "probability": 0.9996631145477295, "box": [422, 32, 346, 625], "points": [[422, 32], [768, 32], [768, 657], [422, 657]], "model": "facebook/detr-resnet-50", "color": "#ffff00", "qid": "98_person", "person_filters": [61, 98], "person_number": "person_1"}]

```

---

<div class="post-metadata">

**Author:** ![ryanwesslen](https://sea2.discourse-cdn.com/flex020/user_avatar/support.prodi.gy/ryanwesslen/32/2969_2.png) [@ryanwesslen](https://support.prodi.gy/u/ryanwesslen)\
**Post date:** [January 4, 2023, 4:24pm UTC](https://support.prodi.gy/t/sublabel-for-ner/4223/8 "2023-01-04T16:24:24Z")

</div>

Providing another support issue that tried to address this question.

> [@Clarification on annotation capabilities](https://support.prodi.gy/t/clarification-on-annotation-capabilities/4721/8):
>
> hi @c00lcoder! Thanks for the clarification. The [before\_db callback](https://prodi.gy/docs/custom-recipes#before_db) could help with the 2nd step to modify the data. Like described previously, it would need to be a two-step process. First you create your bounding boxes, then add the attributes to the spans by iterating over each span separately and adding the choices with the before\_db method to the spans. It's important to know that before\_db callback should be used sparingly and with caution. The [docs](https://prodi.gy/docs/custom-recipes#before_db) mention this: The before\_db callb…
