| import codecs
|
| import numpy as np
|
|
|
|
|
| def get_chunks(seq, tags):
|
| """
|
| tags:dic{'per':1,....}
|
| Args:
|
| seq: [4, 4, 0, 0, ...] sequence of labels
|
| tags: dict["O"] = 4
|
| Returns:
|
| list of (chunk_type, chunk_start, chunk_end)
|
|
|
| Example:
|
| seq = [4, 5, 0, 3]
|
| tags = {"B-PER": 4, "I-PER": 5, "B-LOC": 3}
|
| result = [("PER", 0, 2), ("LOC", 3, 4)]
|
| """
|
| default = tags['O']
|
| idx_to_tag = {idx: tag for tag, idx in tags.items()}
|
| chunks = []
|
|
|
| chunk_type, chunk_start = None, None
|
| for i, tok in enumerate(seq):
|
|
|
| if tok == default and chunk_type is not None:
|
|
|
| chunk = (chunk_type, chunk_start, i)
|
| chunks.append(chunk)
|
| chunk_type, chunk_start = None, None
|
|
|
|
|
| elif tok != default:
|
|
|
|
|
| tok_chunk_class, tok_chunk_type = get_chunk_type(tok, idx_to_tag)
|
| if chunk_type is None:
|
| chunk_type, chunk_start = tok_chunk_type, i
|
| elif tok_chunk_type != chunk_type or tok_chunk_class == "B":
|
| chunk = (chunk_type, chunk_start, i)
|
| chunks.append(chunk)
|
| chunk_type, chunk_start = tok_chunk_type, i
|
| else:
|
| pass
|
|
|
| if chunk_type is not None:
|
| chunk = (chunk_type, chunk_start, len(seq))
|
| chunks.append(chunk)
|
| return chunks
|
|
|
|
|
| def get_chunk_type(tok, idx_to_tag):
|
| """
|
| Args:
|
| tok: id of token, such as 4
|
| idx_to_tag: dictionary {4: "B-PER", ...}
|
| Returns:
|
| tuple: "B", "PER"
|
| """
|
| tag_name = idx_to_tag[tok]
|
| tag_class = tag_name.split('-')[0]
|
| tag_type = tag_name.split('-')[-1]
|
| return tag_class, tag_type
|
|
|
|
|
|
|
| def evaluate(labels_pred, labels, words, tags):
|
| """
|
| words,pred, right: is a sequence, is label index or word index.
|
| Evaluates performance on test set
|
| Args:
|
| sess: tensorflow session
|
| test: dataset that yields tuple of sentences, tags
|
| tags: {tag: index} dictionary
|
| Returns:
|
| accuracy
|
| f1 score
|
| ...
|
| """
|
|
|
|
|
|
|
| index = 0
|
| sents_length = []
|
|
|
| accs = []
|
| correct_preds, total_correct, total_preds = 0., 0., 0.
|
|
|
| for lab, lab_pred, word_sent in zip(labels, labels_pred, words):
|
| word_st = word_sent
|
| lab = lab
|
| lab_pred = lab_pred
|
| accs += [a == b for (a, b) in zip(lab, lab_pred)]
|
| lab_chunks = set(get_chunks(lab, tags))
|
| lab_pred_chunks = set(get_chunks(lab_pred, tags))
|
| correct_preds += len(lab_chunks & lab_pred_chunks)
|
| total_preds += len(lab_pred_chunks)
|
| total_correct += len(lab_chunks)
|
|
|
|
|
|
|
|
|
|
|
| p = correct_preds / total_preds if correct_preds > 0 else 0
|
| r = correct_preds / total_correct if correct_preds > 0 else 0
|
| f1 = 2 * p * r / (p + r) if correct_preds > 0 else 0
|
| acc = np.mean(accs)
|
|
|
|
|
| return acc, f1, p, r
|
|
|
|
|
| def evaluate_each_class(labels_pred, labels, words, tags, class_type):
|
|
|
| index = 0
|
|
|
| accs = []
|
| correct_preds, total_correct, total_preds = 0., 0., 0.
|
| correct_preds_cla_type, total_preds_cla_type, total_correct_cla_type = 0., 0., 0.
|
|
|
| for lab, lab_pred, word_sent in zip(labels, labels_pred, words):
|
| lab_pre_class_type = []
|
| lab_class_type = []
|
|
|
| word_st = word_sent
|
| lab = lab
|
| lab_pred = lab_pred
|
| lab_chunks = get_chunks(lab, tags)
|
| lab_pred_chunks = get_chunks(lab_pred, tags)
|
| for i in range(len(lab_pred_chunks)):
|
| if lab_pred_chunks[i][0] == class_type:
|
| lab_pre_class_type.append(lab_pred_chunks[i])
|
| lab_pre_class_type_c = set(lab_pre_class_type)
|
|
|
| for i in range(len(lab_chunks)):
|
| if lab_chunks[i][0] == class_type:
|
| lab_class_type.append(lab_chunks[i])
|
| lab_class_type_c = set(lab_class_type)
|
|
|
| lab_chunksss = set(lab_chunks)
|
| correct_preds_cla_type += len(lab_pre_class_type_c & lab_chunksss)
|
| total_preds_cla_type += len(lab_pre_class_type_c)
|
| total_correct_cla_type += len(lab_class_type_c)
|
|
|
| p = correct_preds_cla_type / total_preds_cla_type if correct_preds_cla_type > 0 else 0
|
| r = correct_preds_cla_type / total_correct_cla_type if correct_preds_cla_type > 0 else 0
|
| f1 = 2 * p * r / (p + r) if correct_preds_cla_type > 0 else 0
|
|
|
| return f1, p, r
|
|
|
|
|
| if __name__ == '__main__':
|
| max_sent = 10
|
| tags = {'0': 0,
|
| 'B-PER': 1, 'I-PER': 2,
|
| 'B-LOC': 3, 'I-LOC': 4,
|
| 'B-ORG': 5, 'I-ORG': 6,
|
| 'B-OTHER': 7, 'I-OTHER': 8,
|
| 'O': 9}
|
| labels_pred = [
|
| [9, 9, 9, 1, 3, 1, 2, 2, 0, 0],
|
| [9, 9, 9, 1, 3, 1, 2, 0, 0, 0]
|
| ]
|
| labels = [
|
| [9, 9, 9, 9, 3, 1, 2, 2, 0, 0],
|
| [9, 9, 9, 9, 3, 1, 2, 2, 0, 0]
|
| ]
|
| words = [
|
| [0, 0, 0, 0, 0, 3, 6, 8, 5, 7],
|
| [0, 0, 0, 4, 5, 6, 7, 9, 1, 7]
|
| ]
|
| id_to_vocb = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j'}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| acc, f1, p, r = evaluate(labels_pred, labels, words, tags)
|
| print(acc) |