Multilabel BERT Experiments

In this notebook we do some first experiments with BERT: we finetune a BERT model+classifier on each of our datasets separately and compute the accuracy of the resulting classifier on the test data.

For these experiments we use the pytorch_transformers package. It contains a variety of neural network architectures for transfer learning and pretrained models, including BERT and XLNET.

Two different BERT models are relevant for our experiments:

  • BERT-base-uncased: a relatively small BERT model that should already give reasonable results,
  • BERT-large-uncased: a larger model for real state-of-the-art results.

In [1]:
from multilabel import EATINGMEAT_BECAUSE_MAP, EATINGMEAT_BUT_MAP, JUNKFOOD_BECAUSE_MAP, JUNKFOOD_BUT_MAP

label_map = EATINGMEAT_BECAUSE_MAP

In [2]:
import torch

from pytorch_transformers.tokenization_bert import BertTokenizer
from pytorch_transformers.modeling_bert import BertForSequenceClassification

BERT_MODEL = 'bert-large-uncased'
BATCH_SIZE = 16 if "base" in BERT_MODEL else 2
GRADIENT_ACCUMULATION_STEPS = 1 if "base" in BERT_MODEL else 8

tokenizer = BertTokenizer.from_pretrained(BERT_MODEL)

Data

We use the same data as for all our previous experiments. Here we load the training, development and test data for a particular prompt.


In [3]:
import ndjson
import glob
from collections import Counter

prefix = "eatingmeat_because_xl"
train_file = f"../data/interim/{prefix}_train_withprompt.ndjson"
synth_files = glob.glob(f"../data/interim/{prefix}_train_withprompt_allsynth.ndjson")
dev_file = f"../data/interim/{prefix}_dev_withprompt.ndjson"
test_file = f"../data/interim/{prefix}_test_withprompt.ndjson"

with open(train_file) as i:
    train_data = ndjson.load(i)

synth_data = []
for f in synth_files:
    with open(f) as i:
        synth_data += ndjson.load(i)
    
with open(dev_file) as i:
    dev_data = ndjson.load(i)
    
with open(test_file) as i:
    test_data = ndjson.load(i)
    
labels = Counter([item["label"] for item in train_data])
print(labels)
print(len(synth_data))


Counter({'Meat industry produces greenhouse gases and/or uses water - specific numbers': 570, 'Meat industry produces greenhouse gases and/or uses water - general': 548, 'Because as preposition': 166, 'Meat industry harms environment/uses resources w/o mentioning greenhouse gases or water': 70, "Outside of article's scope": 30, 'Meat industry produces greenhouse gases and/or uses water - incorrect numbers or comparison': 12, 'Irrelevant fact from article': 10, 'Meat industry harms animals': 5})
4456

Next, we build the label vocabulary, which maps every label in the training data to an index.


In [4]:
label2idx = {}
idx2label = {}
target_names = []
for item in label_map:
    for label in label_map[item]:
        if label not in target_names:
            idx = len(target_names)
            target_names.append(label)
            label2idx[label] = idx
            idx2label[idx] = label
    
print(label2idx)
print(idx2label)


{'harms environment': 0, 'irrelevant': 1, 'harms animals': 2, 'because as preposition': 3, 'greenhouse gas or water': 4, 'specific numbers': 5, 'outside scope': 6, 'incorrect numbers': 7}
{0: 'harms environment', 1: 'irrelevant', 2: 'harms animals', 3: 'because as preposition', 4: 'greenhouse gas or water', 5: 'specific numbers', 6: 'outside scope', 7: 'incorrect numbers'}

In [5]:
def map_to_multilabel(items):
    return [{"text": item["text"], "label": label_map[item["label"]]} for item in items]

train_data = map_to_multilabel(train_data)
dev_data = map_to_multilabel(dev_data)
synth_data = map_to_multilabel(synth_data)
test_data = map_to_multilabel(test_data)

In [6]:
import random

def sample(train_data, synth_data, label2idx, number):
    """Sample a fixed number of items from every label from
    the training data and test data.
    """
    new_train_data = []
    for label in label2idx:
        data_for_label = [i for i in train_data if i["label"] == label]
        
        # If there is more training data than the required number,
        # take a random sample of n examples from the training data.
        if len(data_for_label) >= number:
            random.shuffle(data_for_label)
            new_train_data += data_for_label[:number]
            
        # If there is less training data than the required number,
        # combine training data with synthetic data.
        elif len(data_for_label) < number:
            
            # Automatically add all training data
            new_train_data += data_for_label
            
            # Compute the required number of additional data
            rest = number-len(data_for_label)
            
            # Collect the synthetic data for the label
            synth_data_for_label = [i for i in synth_data if i["label"] == label]
            
            # If there is more synthetic data than required, 
            # take a random sample from the synthetic data.
            if len(synth_data_for_label) > rest:
                random.shuffle(synth_data_for_label)
                new_train_data += synth_data_for_label[:rest]
            # If there is less synthetic data than required,
            # sample with replacement from this data until we have
            # the required number.
            else:
                new_train_data += random.choices(synth_data_for_label, k=rest)
        
    return new_train_data


def random_sample(train_data, train_size):
    random.shuffle(train_data)
    train_data = train_data[:TRAIN_SIZE]    

#train_data = sample(train_data, synth_data, label2idx, 200)
print("Train data size:", len(train_data))
train_data = train_data + synth_data
print("Train data size:", len(train_data))


Train data size: 1411
Train data size: 5867

Model

We load the pretrained model and put it on a GPU if one is available. We also put the model in "training" mode, so that we can correctly update its internal parameters on the basis of our data sets.


In [7]:
from torch import nn
from pytorch_transformers.modeling_bert import BertPreTrainedModel, BertModel


class BertForMultiLabelSequenceClassification(BertPreTrainedModel):
    r"""
        **labels**: (`optional`) ``torch.LongTensor`` of shape ``(batch_size,)``:
            Labels for computing the sequence classification/regression loss.
            Indices should be in ``[0, ..., config.num_labels - 1]``.
            If ``config.num_labels == 1`` a regression loss is computed (Mean-Square loss),
            If ``config.num_labels > 1`` a classification loss is computed (Cross-Entropy).
    Outputs: `Tuple` comprising various elements depending on the configuration (config) and inputs:
        **loss**: (`optional`, returned when ``labels`` is provided) ``torch.FloatTensor`` of shape ``(1,)``:
            Classification (or regression if config.num_labels==1) loss.
        **logits**: ``torch.FloatTensor`` of shape ``(batch_size, config.num_labels)``
            Classification (or regression if config.num_labels==1) scores (before SoftMax).
        **hidden_states**: (`optional`, returned when ``config.output_hidden_states=True``)
            list of ``torch.FloatTensor`` (one for the output of each layer + the output of the embeddings)
            of shape ``(batch_size, sequence_length, hidden_size)``:
            Hidden-states of the model at the output of each layer plus the initial embedding outputs.
        **attentions**: (`optional`, returned when ``config.output_attentions=True``)
            list of ``torch.FloatTensor`` (one for each layer) of shape ``(batch_size, num_heads, sequence_length, sequence_length)``:
            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention heads.
    Examples::
        tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
        model = BertForSequenceClassification.from_pretrained('bert-base-uncased')
        input_ids = torch.tensor(tokenizer.encode("Hello, my dog is cute")).unsqueeze(0)  # Batch size 1
        labels = torch.tensor([1]).unsqueeze(0)  # Batch size 1
        outputs = model(input_ids, labels=labels)
        loss, logits = outputs[:2]
    """
    def __init__(self, config):
        super(BertForMultiLabelSequenceClassification, self).__init__(config)
        self.num_labels = config.num_labels

        self.bert = BertModel(config)
        self.dropout = nn.Dropout(config.hidden_dropout_prob)
        self.classifier = nn.Linear(config.hidden_size, self.config.num_labels)

        self.apply(self.init_weights)

    def forward(self, input_ids, token_type_ids=None, attention_mask=None, labels=None,
                position_ids=None, head_mask=None):
        outputs = self.bert(input_ids, position_ids=position_ids, token_type_ids=token_type_ids,
                            attention_mask=attention_mask, head_mask=head_mask)
        pooled_output = outputs[1]

        pooled_output = self.dropout(pooled_output)
        logits = self.classifier(pooled_output)

        outputs = (logits,) + outputs[2:]  # add hidden states and attention if they are here

        if labels is not None:
            loss_fct = nn.BCEWithLogitsLoss()
            loss = loss_fct(logits, labels)
            outputs = (loss,) + outputs

        return outputs  # (loss), logits, (hidden_states), (attentions)

In [8]:
model = BertForMultiLabelSequenceClassification.from_pretrained(BERT_MODEL, num_labels=len(label2idx))

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
model.train()


Out[8]:
BertForMultiLabelSequenceClassification(
  (bert): BertModel(
    (embeddings): BertEmbeddings(
      (word_embeddings): Embedding(30522, 1024, padding_idx=0)
      (position_embeddings): Embedding(512, 1024)
      (token_type_embeddings): Embedding(2, 1024)
      (LayerNorm): BertLayerNorm()
      (dropout): Dropout(p=0.1)
    )
    (encoder): BertEncoder(
      (layer): ModuleList(
        (0): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (1): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (2): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (3): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (4): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (5): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (6): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (7): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (8): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (9): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (10): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (11): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (12): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (13): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (14): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (15): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (16): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (17): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (18): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (19): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (20): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (21): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (22): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
        (23): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=1024, out_features=1024, bias=True)
              (key): Linear(in_features=1024, out_features=1024, bias=True)
              (value): Linear(in_features=1024, out_features=1024, bias=True)
              (dropout): Dropout(p=0.1)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=1024, out_features=1024, bias=True)
              (LayerNorm): BertLayerNorm()
              (dropout): Dropout(p=0.1)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=1024, out_features=4096, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=4096, out_features=1024, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1)
          )
        )
      )
    )
    (pooler): BertPooler(
      (dense): Linear(in_features=1024, out_features=1024, bias=True)
      (activation): Tanh()
    )
  )
  (dropout): Dropout(p=0.1)
  (classifier): Linear(in_features=1024, out_features=8, bias=True)
)

Preprocessing

We preprocess the data by turning every example to an InputFeatures item. This item has all the attributes we need for finetuning BERT:

  • input ids: the ids of the tokens in the text
  • input mask: tells BERT what part of the input it should not look at (such as padding tokens)
  • segment ids: tells BERT what segment every token belongs to. BERT can take two different segments as input
  • label id: the id of this item's label

In [9]:
import logging
import numpy as np

logging.basicConfig(format = '%(asctime)s - %(levelname)s - %(name)s -   %(message)s',
                    datefmt = '%m/%d/%Y %H:%M:%S',
                    level = logging.INFO)
logger = logging.getLogger(__name__)

MAX_SEQ_LENGTH=100

class InputFeatures(object):
    """A single set of features of data."""

    def __init__(self, input_ids, input_mask, segment_ids, label_ids):
        self.input_ids = input_ids
        self.input_mask = input_mask
        self.segment_ids = segment_ids
        self.label_ids = label_ids
        

def convert_examples_to_features(examples, label2idx, max_seq_length, tokenizer, verbose=0):
    """Loads a data file into a list of `InputBatch`s."""
    
    features = []
    for (ex_index, ex) in enumerate(examples):
        
        # TODO: should deal better with sentences > max tok length
        input_ids = tokenizer.encode("[CLS] " + ex["text"] + " [SEP]")
        segment_ids = [0] * len(input_ids)
            
        # The mask has 1 for real tokens and 0 for padding tokens. Only real
        # tokens are attended to.
        input_mask = [1] * len(input_ids)

        # Zero-pad up to the sequence length.
        padding = [0] * (max_seq_length - len(input_ids))
        input_ids += padding
        input_mask += padding
        segment_ids += padding

        assert len(input_ids) == max_seq_length
        assert len(input_mask) == max_seq_length
        assert len(segment_ids) == max_seq_length

        label_ids = np.zeros(len(label2idx))
        for label in ex["label"]:
            label_ids[label2idx[label]] = 1
        
        if verbose and ex_index == 0:
            logger.info("*** Example ***")
            logger.info("text: %s" % ex["text"])
            logger.info("input_ids: %s" % " ".join([str(x) for x in input_ids]))
            logger.info("input_mask: %s" % " ".join([str(x) for x in input_mask]))
            logger.info("segment_ids: %s" % " ".join([str(x) for x in segment_ids]))
            logger.info("label:" + str(ex["label"]) + " id: " + str(label_ids))

        features.append(
                InputFeatures(input_ids=input_ids,
                              input_mask=input_mask,
                              segment_ids=segment_ids,
                              label_ids=label_ids))
    return features

train_features = convert_examples_to_features(train_data, label2idx, MAX_SEQ_LENGTH, tokenizer, verbose=0)
dev_features = convert_examples_to_features(dev_data, label2idx, MAX_SEQ_LENGTH, tokenizer)
test_features = convert_examples_to_features(test_data, label2idx, MAX_SEQ_LENGTH, tokenizer, verbose=1)


08/27/2019 15:45:26 - INFO - __main__ -   *** Example ***
08/27/2019 15:45:26 - INFO - __main__ -   text: Large amounts of meat consumption are harming the environment, because it creates one-fifth of the earth's greenhouse gases.
08/27/2019 15:45:26 - INFO - __main__ -   input_ids: 101 2312 8310 1997 6240 8381 2024 7386 2075 1996 4044 1010 2138 2009 9005 2028 1011 3587 1997 1996 3011 1005 1055 16635 15865 1012 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
08/27/2019 15:45:26 - INFO - __main__ -   input_mask: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
08/27/2019 15:45:26 - INFO - __main__ -   segment_ids: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
08/27/2019 15:45:26 - INFO - __main__ -   label:['harms environment', 'greenhouse gas or water', 'specific numbers'] id: [1. 0. 0. 0. 1. 1. 0. 0.]

Next, we initialize data loaders for each of our data sets. These data loaders present the data for training (for example, by grouping them into batches).


In [10]:
import torch
from torch.utils.data import TensorDataset, DataLoader, RandomSampler

def get_data_loader(features, max_seq_length, batch_size, shuffle=True): 

    all_input_ids = torch.tensor([f.input_ids for f in features], dtype=torch.long)
    all_input_mask = torch.tensor([f.input_mask for f in features], dtype=torch.long)
    all_segment_ids = torch.tensor([f.segment_ids for f in features], dtype=torch.long)
    all_label_ids = torch.tensor([f.label_ids for f in features], dtype=torch.float)
    data = TensorDataset(all_input_ids, all_input_mask, all_segment_ids, all_label_ids)

    dataloader = DataLoader(data, shuffle=shuffle, batch_size=batch_size)
    
    return dataloader

train_dataloader = get_data_loader(train_features, MAX_SEQ_LENGTH, BATCH_SIZE)
dev_dataloader = get_data_loader(dev_features, MAX_SEQ_LENGTH, BATCH_SIZE)
test_dataloader = get_data_loader(test_features, MAX_SEQ_LENGTH, BATCH_SIZE, shuffle=False)

Evaluation

Our evaluation method takes a pretrained model and a dataloader. It has the model predict the labels for the items in the data loader, and returns the loss, the correct labels, and the predicted labels.


In [11]:
from torch.nn import Sigmoid

def evaluate(model, dataloader, verbose=False):

    eval_loss = 0
    nb_eval_steps = 0
    predicted_labels, correct_labels = [], []

    for step, batch in enumerate(tqdm(dataloader, desc="Evaluation iteration")):
        batch = tuple(t.to(device) for t in batch)
        input_ids, input_mask, segment_ids, label_ids = batch

        with torch.no_grad():
            tmp_eval_loss, logits = model(input_ids, segment_ids, input_mask, label_ids)

        sig = Sigmoid()
        outputs = sig(logits).to('cpu').numpy()
        label_ids = label_ids.to('cpu').numpy()
        
        predicted_labels += list(outputs >= 0.5)        
        correct_labels += list(label_ids)
                    
        eval_loss += tmp_eval_loss.mean().item()
        nb_eval_steps += 1

    eval_loss = eval_loss / nb_eval_steps
    
    correct_labels = np.array(correct_labels)
    predicted_labels = np.array(predicted_labels)
        
    return eval_loss, correct_labels, predicted_labels

Training

Let's prepare the training. We set the training parameters and choose an optimizer and learning rate scheduler.


In [12]:
from pytorch_transformers.optimization import AdamW, WarmupLinearSchedule

NUM_TRAIN_EPOCHS = 20
LEARNING_RATE = 1e-5
WARMUP_PROPORTION = 0.1

def warmup_linear(x, warmup=0.002):
    if x < warmup:
        return x/warmup
    return 1.0 - x

num_train_steps = int(len(train_data) / BATCH_SIZE / GRADIENT_ACCUMULATION_STEPS * NUM_TRAIN_EPOCHS)

param_optimizer = list(model.named_parameters())
no_decay = ['bias', 'LayerNorm.bias', 'LayerNorm.weight']
optimizer_grouped_parameters = [
    {'params': [p for n, p in param_optimizer if not any(nd in n for nd in no_decay)], 'weight_decay': 0.01},
    {'params': [p for n, p in param_optimizer if any(nd in n for nd in no_decay)], 'weight_decay': 0.0}
    ]

optimizer = AdamW(optimizer_grouped_parameters, lr=LEARNING_RATE, correct_bias=False)
scheduler = WarmupLinearSchedule(optimizer, warmup_steps=100, t_total=num_train_steps)

Now we do the actual training. In each epoch, we present the model with all training data and compute the loss on the training set and the development set. We save the model whenever the development loss improves. We end training when we haven't seen an improvement of the development loss for a specific number of epochs (the patience).

Optionally, we use gradient accumulation to accumulate the gradient for several training steps. This is useful when we want to use a larger batch size than our current GPU allows us to do.


In [13]:
import os
from tqdm import trange
from tqdm import tqdm_notebook as tqdm
from sklearn.metrics import classification_report, precision_recall_fscore_support

OUTPUT_DIR = "/tmp/"
MODEL_FILE_NAME = "pytorch_model.bin"
PATIENCE = 5

global_step = 0
model.train()
loss_history = []
best_epoch = 0
for epoch in trange(int(NUM_TRAIN_EPOCHS), desc="Epoch"):
    tr_loss = 0
    nb_tr_examples, nb_tr_steps = 0, 0
    for step, batch in enumerate(tqdm(train_dataloader, desc="Training iteration")):
        batch = tuple(t.to(device) for t in batch)
        input_ids, input_mask, segment_ids, label_ids = batch
        outputs = model(input_ids, segment_ids, input_mask, label_ids)
        loss = outputs[0]
        
        if GRADIENT_ACCUMULATION_STEPS > 1:
            loss = loss / GRADIENT_ACCUMULATION_STEPS

        loss.backward()

        tr_loss += loss.item()
        nb_tr_examples += input_ids.size(0)
        nb_tr_steps += 1
        if (step + 1) % GRADIENT_ACCUMULATION_STEPS == 0:
            lr_this_step = LEARNING_RATE * warmup_linear(global_step/num_train_steps, WARMUP_PROPORTION)
            for param_group in optimizer.param_groups:
                param_group['lr'] = lr_this_step
            optimizer.step()
            optimizer.zero_grad()
            global_step += 1

    dev_loss, _, _ = evaluate(model, dev_dataloader)
    
    print("Loss history:", loss_history)
    print("Dev loss:", dev_loss)
    
    if len(loss_history) == 0 or dev_loss < min(loss_history):
        model_to_save = model.module if hasattr(model, 'module') else model
        output_model_file = os.path.join(OUTPUT_DIR, MODEL_FILE_NAME)
        torch.save(model_to_save.state_dict(), output_model_file)
        best_epoch = epoch
    
    if epoch-best_epoch >= PATIENCE: 
        print("No improvement on development set. Finish training.")
        break
        
    
    loss_history.append(dev_loss)


Epoch:   0%|          | 0/20 [00:00<?, ?it/s]

Loss history: []
Dev loss: 0.12213541412105162
Epoch:   5%|▌         | 1/20 [05:45<1:49:32, 345.93s/it]

Loss history: [0.12213541412105162]
Dev loss: 0.0877677650617746
Epoch:  10%|█         | 2/20 [11:32<1:43:48, 346.02s/it]

Loss history: [0.12213541412105162, 0.0877677650617746]
Dev loss: 0.06956643640296534
Epoch:  15%|█▌        | 3/20 [17:18<1:38:01, 345.99s/it]

Epoch:  20%|██        | 4/20 [23:02<1:32:10, 345.66s/it]
Loss history: [0.12213541412105162, 0.0877677650617746, 0.06956643640296534]
Dev loss: 0.07502751060140629

Epoch:  25%|██▌       | 5/20 [28:47<1:26:20, 345.39s/it]
Loss history: [0.12213541412105162, 0.0877677650617746, 0.06956643640296534, 0.07502751060140629]
Dev loss: 0.08636674445006065

Epoch:  30%|███       | 6/20 [34:32<1:20:33, 345.23s/it]
Loss history: [0.12213541412105162, 0.0877677650617746, 0.06956643640296534, 0.07502751060140629, 0.08636674445006065]
Dev loss: 0.09042651116033085

Epoch:  35%|███▌      | 7/20 [40:17<1:14:45, 345.06s/it]
Loss history: [0.12213541412105162, 0.0877677650617746, 0.06956643640296534, 0.07502751060140629, 0.08636674445006065, 0.09042651116033085]
Dev loss: 0.10135477319515

Loss history: [0.12213541412105162, 0.0877677650617746, 0.06956643640296534, 0.07502751060140629, 0.08636674445006065, 0.09042651116033085, 0.10135477319515]
Dev loss: 0.09101424391944117
No improvement on development set. Finish training.

Results

We load the pretrained model, set it to evaluation mode and compute its performance on the training, development and test set. We print out an evaluation report for the test set.

Note that different runs will give slightly different results.


In [14]:
from tqdm import tqdm_notebook as tqdm

output_model_file = "/tmp/pytorch_model.bin"
print("Loading model from", output_model_file)
device="cpu"

model_state_dict = torch.load(output_model_file, map_location=lambda storage, loc: storage)
model = BertForMultiLabelSequenceClassification.from_pretrained(BERT_MODEL, state_dict=model_state_dict, num_labels=len(label2idx))
model.to(device)

model.eval()
_, test_correct, test_predicted = evaluate(model, test_dataloader, verbose=True)


Loading model from /tmp/pytorch_model.bin
08/27/2019 16:31:30 - INFO - pytorch_transformers.modeling_utils -   loading configuration file https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased-config.json from cache at /home/yves/.cache/torch/pytorch_transformers/6dfaed860471b03ab5b9acb6153bea82b6632fb9bbe514d3fff050fe1319ee6d.4c88e2dec8f8b017f319f6db2b157fee632c0860d9422e4851bd0d6999f9ce38
08/27/2019 16:31:30 - INFO - pytorch_transformers.modeling_utils -   Model config {
  "attention_probs_dropout_prob": 0.1,
  "finetuning_task": null,
  "hidden_act": "gelu",
  "hidden_dropout_prob": 0.1,
  "hidden_size": 1024,
  "initializer_range": 0.02,
  "intermediate_size": 4096,
  "layer_norm_eps": 1e-12,
  "max_position_embeddings": 512,
  "num_attention_heads": 16,
  "num_hidden_layers": 24,
  "num_labels": 8,
  "output_attentions": false,
  "output_hidden_states": false,
  "torchscript": false,
  "type_vocab_size": 2,
  "vocab_size": 30522
}

08/27/2019 16:31:31 - INFO - pytorch_transformers.modeling_utils -   loading weights file https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased-pytorch_model.bin from cache at /home/yves/.cache/torch/pytorch_transformers/54da47087cc86ce75324e4dc9bbb5f66c6e83a7c6bd23baea8b489acc8d09aa4.4d5343a4b979c4beeaadef17a0453d1bb183dd9b084f58b84c7cc781df343ae6


In [15]:
all_correct = 0
fp, fn, tp, tn = 0, 0, 0, 0
for c, p in zip(test_correct, test_predicted):
    if sum(c == p) == len(c):
        all_correct +=1
    for ci, pi in zip(c, p):
        if pi == 1 and ci == 1:
            tp += 1
            same = 1
        elif pi == 1 and ci == 0:
            fp += 1
        elif pi == 0 and ci == 1:
            fn += 1
        else:
            tn += 1
            same =1
            
precision = tp/(tp+fp)
recall = tp/(tp+fn)
print("P:", precision)
print("R:", recall)
print("A:", all_correct/len(test_correct))


P: 0.979933110367893
R: 0.9606557377049181
A: 0.8958333333333334

In [16]:
for item, predicted, correct in zip(test_data, test_predicted, test_correct):
    correct_labels = [idx2label[i] for i, l in enumerate(correct) if l == 1]
    predicted_labels = [idx2label[i] for i, l in enumerate(predicted) if l == 1]
    print("{}#{}#{}".format(item["text"], ";".join(correct_labels), ";".join(predicted_labels)))


Large amounts of meat consumption are harming the environment, because it creates one-fifth of the earth's greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it affects the environment.#harms environment#harms environment
Large amounts of meat consumption are harming the environment, because it creates greenhouse gases and uses a lot of water resources.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because it is causing a very excessive amount of greenhouse gasses.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because of greenhouse gases from transportation and animals themselves.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because of the amount of water used to raise livestock and the carbon impact of transporting meat products.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because production of meat produces huge amounts of greenhouse gasses#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because this process is responsible for almost one-fifth of the earth's greenhouse gases which is harmful for the environment.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because raising animals and transporting meat releases massive amounts of greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because natural resources are used raising and transporting products.#harms environment;greenhouse gas or water#harms environment
Large amounts of meat consumption are harming the environment, because raising the livestock and transporting it accounts for almost 1/5 of the earth's greenhouse gases#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because raising livestock produces more greenhouse gas.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because it is hurting the earth by contributing to one-fifth of the earth's greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it increases the amount of greenhouse gases present in the atmosphere#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because raising and transporting meat creates more greenhouse gases than driving most vehicles combined.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because of the greenhouse gases it produces, and water it uses.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because it takes a lot of energy, resources, and effort to sustain the meat industry.#harms environment#harms environment
Large amounts of meat consumption are harming the environment, because raising and transporting livestock is causing a large portion of the greenhouse gases produced.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because it hurts the economy and takes away jobs.#irrelevant#irrelevant
Large amounts of meat consumption are harming the environment, because greenhouse gases#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because it produces a large amount of greenhouse gas and water.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because of the transportation and upkeep of the livestock we depend on for the meat.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because transportation of animals causes pollution.#harms environment#harms environment
Large amounts of meat consumption are harming the environment, because raising and transporting livestock causes 1/5 of all green house gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because according to the article they create a lot of greenhouse gases#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because it requires a lot of resources contributing to 20% of green house gases generated by man.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because the meat industry produces 1/5 of the green house gasses.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it is a large contributor to greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because it does not say#outside scope#
Large amounts of meat consumption are harming the environment, because of the enormous amount of greenhouse gases produced by raising and transporting cattles#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because raising animals for food cause water pollution and animals suffering.#harms environment#harms environment
Large amounts of meat consumption are harming the environment, because they produce almost one-fifth of greenhouse gases, as well as consuming almost half of all water used in the US.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it creates one fifth of earth's greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because greenhouses gases#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because a large portion of greenhouse gasses are caused by raising and transporting meat.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because the more we consume, the higher amounts of raising and transporting animal meat creates more greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because the production of meats create greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because transporting the meat causes the use of a lot of energy and pollution.#harms environment#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because we kill too many animals#outside scope#outside scope
Large amounts of meat consumption are harming the environment, because of the increased amounts of greenhouse gases that result from it.#because as preposition#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because raising and transporting animals accounts for 20% of greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because meat production creates nearly twenty-five percent of greenhouse gases in our planet's atmosphere.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because of the greenhouse gas emissions that come from the meat industry.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because it produces about one fifth of the greenhouse gases in the earth.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it is creating a lot of greenhouse gas and using up water.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because they contribute to higher greenhouse gases and water consumption.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because raising and transporting meat causes greenhouse gases and too much water is used.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because of the greenhouse gases produced by the raising of animals and transporting the meat.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because the meat industry produces 1/5th of all greenhouse gases on Earth.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because raising animals and transporting meat produces high amounts of greenhouse gasses.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because of what is required to produce enough for everyone.#because as preposition#
Large amounts of meat consumption are harming the environment, because continued demand puts an enormous strain on the environment, roughly 20% of greenhouse gasses produced comes from the meat industry#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because Half of the US water consumption is used for raising livestock.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because raising and transporting livestock creates a massive amount of greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because of the greenhouse gases produced and quantity of water consumed in the production of meat.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because they emit more than one fifth of overall greenhouse gases#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because the release of greenhouse gasses.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because the raising and transportation of the animals creates greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because of green house effect is increasing!#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because meat production creates huge amounts of greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because they generate one fifth of greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because exporting and greenhouse gases increase as a result.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because raising the livestock and transporting meat produces one-fifth of the earth's greenhouse gases, which is more than that produced by cars, trucks, trains, and airplanes combined.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it produces more green house gases from the delivery trucks.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because raising animals and transporting meats cause almost one-fifth of greenhouse gases on earth.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because almost one fifth of the world's greenhouse gases are created by raising animals and transporting meat.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because raising and transporting animals produces 1/5 of earth's greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because the meat industry produces one-fifth of the greenhouse gases on earth, more than cars, trucks, trains, and planes combined.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it contributes to the creation of 1/5 of the Earth's greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because more domestic animals that are suppose to complete the Eco circle are killed every day.#harms animals#outside scope
Large amounts of meat consumption are harming the environment, because they account for 1/5 of greenhouse gasses#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because one-fifth of the earth’s greenhouse gases are produced by raising and transporting meat#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it is responsible for one fifths of the greenhouse gas emissions.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it produces more greenhouse gases than cars, planes, and trains all together; one fifth in total.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because almost one third of the earths greenhouse gases come from raising animals and transporting them#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because of the thought that greenhouse gas is emitted from raising meat and a large amount of water is consumed.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because the process involved with bringing meat to grocery stores takes up quite a large portion of greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because it creates the earth's greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because they contribute significantly to greenhouse gas production.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because transporting meat produces 1/5 of the earth's greenhouse gases and almost 1/2 of water usage in the US is dedicated to raising livestock.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because of gases being relased#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because raising and transporting meat is responsible for creating around one-fifth of the earth's greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because greenhouse gasses produced and environmental impact.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because raising cattle and shipping out the meat causes more gas in the environment than cars, trucks and planes put together.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because they produce far too many green house gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because it increases greenhouse gases more than cars, trucks, trains, and airplanes combined.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because raising all the animals and transporting meat creates at least one-fifth of the earth’s greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because transport of this creates 1/5 of Earth's greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it generates greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because they increase the amount of greenhouse emissions.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because it is producing  one-fifth of the earth's greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because of the large amount of water used  and greenhouse gases emitted by livestock.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because raising livestock and transporting meat produces almost one-fifth of the earth's greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because the transport and production stages of meat cause a massive amount of damage to the environment.#harms environment#harms environment
Large amounts of meat consumption are harming the environment, because raising and transporting meat generates almost 1/5 of the world's greenhouse gasses.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because one-fifth of the earth's greenhouse gases are produced by the meat industry.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it creates a large amount of greenhouse gases, and also uses a large amount of water to raise the animals.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because raising livestock for consumption creates 1/5th of the earth's greenhouse gases, and uses large amounts of water.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because they are putting out more  green house gasses that is coming from all the gasses from shipping these animals for people to eat.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because of the greenhouse gas emissions and water needs involved in raising livestock.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because raising animals and transporting animal meat results in about one-fifth of harmful greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it produces gases#harms environment;greenhouse gas or water#harms environment
Large amounts of meat consumption are harming the environment, because of the greenhouse gases that are produced transporting the meat.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because of the amount of greenhouse gasses  associated with production and transportation of meat.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because the raising and transporting of meat is a large contributor  of green house gases#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because the cost of transporting these meat products.#harms environment#harms environment
Large amounts of meat consumption are harming the environment, because of the green house gases it causes when raising the animal#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because they are creating an excess of greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because Most of the beef produced domestically is eaten by Americans#irrelevant#
Large amounts of meat consumption are harming the environment, because Growing cow to selling butchered meat now we are exporting our meats is bad carbon footprint.#harms environment#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because it creates increased greenhouse gases#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because raising and transporting live-stock adds large amounts of greenhouse gasses to our planet's atmosphere.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because the greenhouse gases caused by raising and transporting animals that will be consumed as meat are greater than that of all cars, trucks, trains, and airplanes combined.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because raising and transporting animals creates about 1/5 of the earth's greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because of greenhouse gases.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because half the water in the US is used to raise livestock.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it creates one fifth of earths greenhouse gases#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because the raising and transporting of meat creates one fifth of earths greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because one-fifth of the earth’s greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because of greenhouse gases that produced by raising livestock as well as transporting animals in vehicles.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because many greenhouse gasses are emitted in the raising and transporting of livestock for the meat market.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because the people kill a lot of animal to satisfy the people desire.#outside scope#outside scope
Large amounts of meat consumption are harming the environment, because of greenhouse gases produced.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because the production of meat causes greenhouse gasses.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because the rate at which we farm domestic animals creates one-fifth of Earth's greenhouse gasses, and that industry is only expanding.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because they comprise one-fifth of the Earth's greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because raising animals and transporting them account for 20% of greenhouse gases on earth.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it is creating greenhouse gases and uses up a lot of water.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because this creates almost one fifth of the earth's greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because the transportion of meat creates large amounts of greenhouse gases.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because of greenhouse gases produced by cars, trucks, trains, and airplanes combined.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because the cost of transporting the meats causes 1/5 of greenhouse gasses.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because hurting the economy and taking away precious jobs.#irrelevant#irrelevant
Large amounts of meat consumption are harming the environment, because between raising livestock and transporting said livestock about one fifth of all greenhouse gasses are created as well as over half of the water in america is going to livestock.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because of carbon emissions.#because as preposition#because as preposition
Large amounts of meat consumption are harming the environment, because raising animals for food creates large amounts of greenhouses gasses that contribute to global warming and half of the water we use is used on raising livestock for food.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because meat production releases emissions into the atmosphere and uses precious water resources.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because processing meat uses resources and creates pollution.#harms environment#harms environment
Large amounts of meat consumption are harming the environment, because raising animals and transportation of meat uses a significant amount of the earth's greenhouses gases, while the raising of livestock also uses half of the water used in the U.S.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because transporting meat and raising the animals  creates almost one-fifth of greenhouse gases.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because it takes a lot of resources such as water and land to raise livestock.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because THEY PRODUCE 1/5 THE GREENHOUSE GASES#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water;specific numbers
Large amounts of meat consumption are harming the environment, because the meat industry generates insane amounts of greenhouse gases and consumes almost half of America's water usage.#harms environment;greenhouse gas or water;specific numbers#harms environment;greenhouse gas or water
Large amounts of meat consumption are harming the environment, because most of our water sources are used for the animals we are raising for meat.#harms environment;greenhouse gas or water#harms environment;greenhouse gas or water

In [ ]: