From c6fe4f3f5c485df4ed8161f345aa9afa7f3aa6c8 Mon Sep 17 00:00:00 2001 From: LZR <1004586949@qq.com> Date: Tue, 23 Jul 2024 19:17:39 +0800 Subject: [PATCH] Upload the tool --- .gitignore | 15 + LICENSE | 21 + README.md | 91 +++ aste/__init__.py | 0 aste/analysis.py | 193 ++++++ aste/data_utils.py | 593 ++++++++++++++++++ aste/utils.py | 175 ++++++ aste/wrapper.py | 268 ++++++++ dataset/14lap.csv | 328 ++++++++++ format_output.py | 77 +++ main.py | 60 ++ pred.py | 51 ++ pred/14lap/14lap_pred_seed18.csv | 328 ++++++++++ pred/14lap/14lap_pred_seed18_formatted.csv | 329 ++++++++++ requirements.txt | 14 + semple_data.txt | 100 +++ setup.sh | 25 + span_model/__init__.py | 0 span_model/data/__init__.py | 2 + span_model/data/dataset_readers/document.py | 427 +++++++++++++ span_model/data/dataset_readers/span_model.py | 224 +++++++ span_model/predictors/__init__.py | 1 + span_model/predictors/span_model.py | 73 +++ span_model/training/f1.py | 17 + span_model/training/ner_metrics.py | 76 +++ span_model/training/relation_metrics.py | 63 ++ train.py | 39 ++ training_config/config.json | 121 ++++ 28 files changed, 3711 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 aste/__init__.py create mode 100644 aste/analysis.py create mode 100644 aste/data_utils.py create mode 100644 aste/utils.py create mode 100644 aste/wrapper.py create mode 100644 dataset/14lap.csv create mode 100644 format_output.py create mode 100644 main.py create mode 100644 pred.py create mode 100644 pred/14lap/14lap_pred_seed18.csv create mode 100644 pred/14lap/14lap_pred_seed18_formatted.csv create mode 100644 requirements.txt create mode 100644 semple_data.txt create mode 100644 setup.sh create mode 100644 span_model/__init__.py create mode 100644 span_model/data/__init__.py create mode 100644 span_model/data/dataset_readers/document.py create mode 100644 span_model/data/dataset_readers/span_model.py create mode 100644 span_model/predictors/__init__.py create mode 100644 span_model/predictors/span_model.py create mode 100644 span_model/training/f1.py create mode 100644 span_model/training/ner_metrics.py create mode 100644 span_model/training/relation_metrics.py create mode 100644 train.py create mode 100644 training_config/config.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..18feff4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*__pycache__ +*.pyc +*.log +*.swp +tags +punkt.zip +wordnet.zip +.idea/ +aste/data/ +aste/temp_data/ +models/ +model_outputs/ +outputs/ +pretrained_weight/* +!pretrained_weight/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f0dea9c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Chia Yew Ken + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..db9cf24 --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ +工具文档 + +工具功能: + +提取句子中的(Aspect, Opinion, Sentiment)三元组。 + +例如:It also has lots of other Korean dishes that are affordable and just as yummy . + +对应的三元组为[(Korean dishes, affordable, POSITIVE), (Korean dishes, yummy, POSITIVE)] + + + +环境配置: + +使用python3.7(推荐使用虚拟环境,如conda) + +安装依赖:bash setup.sh + +修改训练配置:training_config/config.json + + + +数据格式: + +·输入(可参考dataset/14lap.csv): + +输入为一个csv文件{data}.csv,每行是一个待测语句,存放在dataset目录下。 + +·输出(可参考pred/14lap): + +输出为pred/{data}目录下的csv文件。每一行的格式为: + +sentence#### #### ####[triplet_0, ..., triplet_n] + +其中每个triplet为(span_a, span_b, label),每个span是一个单词索引的列表,表示起始和结束处的索引。而label有三个可能值:’POS’, ‘NEU’, ‘NEG’,分别表示Sentiment是’Positive’, ‘Neutral’, ‘Negative’。 + +例如,It is a great size and amazing windows 8 included ! .#### #### ####[([4], [3], 'POS'), ([7, 8], [6], 'POS')] + +这个结果中,对于原句提取出的三元组为(size, great, positive), (windows 8, amazing, positive) + + + +运行: + +1.(可选)修改training_config/config.json中的训练参数 + +2.指定入口脚本main.py中的参数 + +参数说明: + +dataset: 待预测的csv文件名称。 + using_train: 选择重新训练数据(using_train=True),还是直接使用pretrain_weight中的权重(using_train=False)。你可以从这里下载预训练权重,并把它放在pretrained_weight目录下。 + model_name: 训练采用的数据集名称(或者使用的预训练权重的数据名称)。训练后产生的日志和权重会保存在outputs/{model_name}目录中。model_name目前的可选值有:’14lap’, ‘14res’, ‘15res’, ‘16res’ + random_seed: 随机种子。 + +3.运行python main.py ,然后可以在pred/{data}目录下查看提取结果 + + + +引用: + +@inproceedings{xu-etal-2021-learning, + + title = "Learning Span-Level Interactions for Aspect Sentiment Triplet Extraction", + + author = "Xu, Lu and + + Chia, Yew Ken and + + Bing, Lidong", + + booktitle = "Proceedings of the 59th Annual Meeting of the Association for Computational Linguistics and the 11th International Joint Conference on Natural Language Processing (Volume 1: Long Papers)", + + month = aug, + + year = "2021", + + address = "Online", + + publisher = "Association for Computational Linguistics", + + url = "https://aclanthology.org/2021.acl-long.367", + + doi = "10.18653/v1/2021.acl-long.367", + + pages = "4755--4766", + + abstract = "Aspect Sentiment Triplet Extraction (ASTE) is the most recent subtask of ABSA which outputs triplets of an aspect target, its associated sentiment, and the corresponding opinion term. Recent models perform the triplet extraction in an end-to-end manner but heavily rely on the interactions between each target word and opinion word. Thereby, they cannot perform well on targets and opinions which contain multiple words. Our proposed span-level approach explicitly considers the interaction between the whole spans of targets and opinions when predicting their sentiment relation. Thus, it can make predictions with the semantics of whole spans, ensuring better sentiment consistency. To ease the high computational cost caused by span enumeration, we propose a dual-channel span pruning strategy by incorporating supervision from the Aspect Term Extraction (ATE) and Opinion Term Extraction (OTE) tasks. This strategy not only improves computational efficiency but also distinguishes the opinion and target spans more properly. Our framework simultaneously achieves strong performance for the ASTE as well as ATE and OTE tasks. In particular, our analysis shows that our span-level approach achieves more significant improvements over the baselines on triplets with multi-word targets or opinions.", + +} + diff --git a/aste/__init__.py b/aste/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aste/analysis.py b/aste/analysis.py new file mode 100644 index 0000000..41a3bdb --- /dev/null +++ b/aste/analysis.py @@ -0,0 +1,193 @@ +import json +import random +import sys +from pathlib import Path +from typing import List + +import _jsonnet +import numpy as np +import torch +from allennlp.commands.train import train_model +from allennlp.common import Params +from allennlp.data import DatasetReader, Vocabulary, DataLoader +from allennlp.models import Model +from allennlp.training import Trainer +from fire import Fire +from tqdm import tqdm + +from data_utils import Data, Sentence +from wrapper import SpanModel, safe_divide + + +def set_seed(seed: int): + random.seed(seed) + np.random.seed(seed) + torch.manual_seed(seed) + + +def test_load( + path: str = "training_config/config.json", + path_train: str = "outputs/14lap/seed_0/temp_data/train.json", + path_dev: str = "outputs/14lap/seed_0/temp_data/validation.json", + save_dir="outputs/temp", +): + # Register custom modules + sys.path.append(".") + from span_model.data.dataset_readers.span_model import SpanModelReader + + assert SpanModelReader is not None + params = Params.from_file( + path, + params_overrides=dict( + train_data_path=path_train, + validation_data_path=path_dev, + test_data_path=path_dev, + ), + ) + + train_model(params, serialization_dir=save_dir, force=True) + breakpoint() + + config = json.loads(_jsonnet.evaluate_file(path)) + set_seed(config["random_seed"]) + reader = DatasetReader.from_params(Params(config["dataset_reader"])) + data_train = reader.read(path_train) + data_dev = reader.read(path_dev) + vocab = Vocabulary.from_instances(data_train + data_dev) + model = Model.from_params(Params(config["model"]), vocab=vocab) + + data_train.index_with(vocab) + data_dev.index_with(vocab) + trainer = Trainer.from_params( + Params(config["trainer"]), + model=model, + data_loader=DataLoader.from_params( + Params(config["data_loader"]), dataset=data_train + ), + validation_data_loader=DataLoader.from_params( + Params(config["data_loader"]), dataset=data_dev + ), + serialization_dir=save_dir, + ) + breakpoint() + trainer.train() + breakpoint() + + +class Scorer: + name: str = "" + + def run(self, path_pred: str, path_gold: str) -> dict: + pred = Data.load_from_full_path(path_pred) + gold = Data.load_from_full_path(path_gold) + assert pred.sentences is not None + assert gold.sentences is not None + assert len(pred.sentences) == len(gold.sentences) + num_pred = 0 + num_gold = 0 + num_correct = 0 + + for i in range(len(gold.sentences)): + tuples_pred = self.make_tuples(pred.sentences[i]) + tuples_gold = self.make_tuples(gold.sentences[i]) + num_pred += len(tuples_pred) + num_gold += len(tuples_gold) + for p in tuples_pred: + for g in tuples_gold: + if p == g: + num_correct += 1 + + precision = safe_divide(num_correct, num_pred) + recall = safe_divide(num_correct, num_gold) + + info = dict( + precision=precision, + recall=recall, + score=safe_divide(2 * precision * recall, precision + recall), + ) + return info + + def make_tuples(self, sent: Sentence) -> List[tuple]: + raise NotImplementedError + + +class SentimentTripletScorer(Scorer): + name: str = "sentiment triplet" + + def make_tuples(self, sent: Sentence) -> List[tuple]: + return [(t.o_start, t.o_end, t.t_start, t.t_end, t.label) for t in sent.triples] + + +class TripletScorer(Scorer): + name: str = "triplet" + + def make_tuples(self, sent: Sentence) -> List[tuple]: + return [(t.o_start, t.o_end, t.t_start, t.t_end) for t in sent.triples] + + +class OpinionScorer(Scorer): + name: str = "opinion" + + def make_tuples(self, sent: Sentence) -> List[tuple]: + return sorted(set((t.o_start, t.o_end) for t in sent.triples)) + + +class TargetScorer(Scorer): + name: str = "target" + + def make_tuples(self, sent: Sentence) -> List[tuple]: + return sorted(set((t.t_start, t.t_end) for t in sent.triples)) + + +class OrigScorer(Scorer): + name: str = "orig" + + def make_tuples(self, sent: Sentence) -> List[tuple]: + raise NotImplementedError + + def run(self, path_pred: str, path_gold: str) -> dict: + model = SpanModel(save_dir="", random_seed=0) + return model.score(path_pred, path_gold) + + +def run_eval_domains( + save_dir_template: str, + path_test_template: str, + random_seeds: List[int] = (0, 1, 2, 3, 4), + domain_names: List[str] = ("hotel", "restaurant", "laptop"), +): + print(locals()) + all_results = {} + + for domain in domain_names: + results = [] + for seed in tqdm(random_seeds): + model = SpanModel(save_dir=save_dir_template.format(seed), random_seed=0) + path_pred = str(Path(model.save_dir, f"pred_{domain}.txt")) + path_test = path_test_template.format(domain) + if not Path(path_pred).exists(): + model.predict(path_test, path_pred) + results.append(model.score(path_pred, path_test)) + + precision = sum(r["precision"] for r in results) / len(random_seeds) + recall = sum(r["recall"] for r in results) / len(random_seeds) + score = safe_divide(2 * precision * recall, precision + recall) + all_results[domain] = dict(p=precision, r=recall, f=score) + for k, v in all_results.items(): + print(k, v) + + +def test_scorer(path_pred: str, path_gold: str): + for scorer in [ + OpinionScorer(), + TargetScorer(), + TripletScorer(), + SentimentTripletScorer(), + OrigScorer(), + ]: + print(scorer.name) + print(scorer.run(path_pred, path_gold)) + + +if __name__ == "__main__": + Fire() diff --git a/aste/data_utils.py b/aste/data_utils.py new file mode 100644 index 0000000..86cbc18 --- /dev/null +++ b/aste/data_utils.py @@ -0,0 +1,593 @@ +import ast +import copy +import json +import os +from collections import Counter +from enum import Enum +from pathlib import Path +from typing import Dict, List, Optional, Set, Tuple + +import numpy as np +import pandas as pd +from fire import Fire +from pydantic import BaseModel +from sklearn.metrics import classification_report + +from .utils import count_joins, get_simple_stats + +RawTriple = Tuple[List[int], int, int, int, int] +Span = Tuple[int, int] + + +class SplitEnum(str, Enum): + train = "train" + dev = "dev" + test = "test" + + +class LabelEnum(str, Enum): + positive = "POS" + negative = "NEG" + neutral = "NEU" + opinion = "OPINION" + target = "TARGET" + + @classmethod + def as_list(cls): + return [cls.neutral, cls.positive, cls.negative] + + @classmethod + def i_to_label(cls, i: int): + return cls.as_list()[i] + + @classmethod + def label_to_i(cls, label) -> int: + return cls.as_list().index(label) + + +class SentimentTriple(BaseModel): + o_start: int + o_end: int + t_start: int + t_end: int + label: LabelEnum + + @classmethod + def make_dummy(cls): + return cls(o_start=0, o_end=0, t_start=0, t_end=0, label=LabelEnum.neutral) + + @property + def opinion(self) -> Tuple[int, int]: + return self.o_start, self.o_end + + @property + def target(self) -> Tuple[int, int]: + return self.t_start, self.t_end + + @classmethod + def from_raw_triple(cls, x: RawTriple): + (o_start, o_end), polarity, direction, gap_a, gap_b = x + # Refer: TagReader + if direction == 0: + t_end = o_start - gap_a + t_start = o_start - gap_b + elif direction == 1: + t_start = gap_a + o_start + t_end = gap_b + o_start + else: + raise ValueError + + return cls( + o_start=o_start, + o_end=o_end, + t_start=t_start, + t_end=t_end, + label=LabelEnum.i_to_label(polarity), + ) + + def to_raw_triple(self) -> RawTriple: + polarity = LabelEnum.label_to_i(self.label) + if self.t_start < self.o_start: + direction = 0 + gap_a, gap_b = self.o_start - self.t_end, self.o_start - self.t_start + else: + direction = 1 + gap_a, gap_b = self.t_start - self.o_start, self.t_end - self.o_start + return [self.o_start, self.o_end], polarity, direction, gap_a, gap_b + + def as_text(self, tokens: List[str]) -> str: + opinion = " ".join(tokens[self.o_start : self.o_end + 1]) + target = " ".join(tokens[self.t_start : self.t_end + 1]) + return f"{opinion}-{target} ({self.label})" + + +class TripleHeuristic(BaseModel): + @staticmethod + def run( + opinion_to_label: Dict[Span, LabelEnum], + target_to_label: Dict[Span, LabelEnum], + ) -> List[SentimentTriple]: + # For each target, pair with the closest opinion (and vice versa) + spans_o = list(opinion_to_label.keys()) + spans_t = list(target_to_label.keys()) + pos_o = np.expand_dims(np.array(spans_o).mean(axis=-1), axis=1) + pos_t = np.expand_dims(np.array(spans_t).mean(axis=-1), axis=0) + dists = np.absolute(pos_o - pos_t) + raw_triples: Set[Tuple[int, int, LabelEnum]] = set() + + closest = np.argmin(dists, axis=1) + for i, span in enumerate(spans_o): + raw_triples.add((i, int(closest[i]), opinion_to_label[span])) + closest = np.argmin(dists, axis=0) + for i, span in enumerate(spans_t): + raw_triples.add((int(closest[i]), i, target_to_label[span])) + + triples = [] + for i, j, label in raw_triples: + os, oe = spans_o[i] + ts, te = spans_t[j] + triples.append( + SentimentTriple(o_start=os, o_end=oe, t_start=ts, t_end=te, label=label) + ) + return triples + + +class TagMaker(BaseModel): + @staticmethod + def run(spans: List[Span], labels: List[LabelEnum], num_tokens: int) -> List[str]: + raise NotImplementedError + + +class BioesTagMaker(TagMaker): + @staticmethod + def run(spans: List[Span], labels: List[LabelEnum], num_tokens: int) -> List[str]: + tags = ["O"] * num_tokens + for (start, end), lab in zip(spans, labels): + assert end >= start + length = end - start + 1 + if length == 1: + tags[start] = f"S-{lab}" + else: + tags[start] = f"B-{lab}" + tags[end] = f"E-{lab}" + for i in range(start + 1, end): + tags[i] = f"I-{lab}" + return tags + + +class Sentence(BaseModel): + tokens: List[str] + pos: List[str] + weight: int + id: int + is_labeled: bool + triples: List[SentimentTriple] + spans: List[Tuple[int, int, LabelEnum]] = [] + + def extract_spans(self) -> List[Tuple[int, int, LabelEnum]]: + spans = [] + for t in self.triples: + spans.append((t.o_start, t.o_end, LabelEnum.opinion)) + spans.append((t.t_start, t.t_end, LabelEnum.target)) + spans = sorted(set(spans)) + return spans + + def as_text(self) -> str: + tokens = list(self.tokens) + for t in self.triples: + tokens[t.o_start] = "(" + tokens[t.o_start] + tokens[t.o_end] = tokens[t.o_end] + ")" + tokens[t.t_start] = "[" + tokens[t.t_start] + tokens[t.t_end] = tokens[t.t_end] + "]" + return " ".join(tokens) + + @classmethod + def from_line_format(cls, text: str): + front, back = text.split("#### #### ####") + tokens = front.split(" ") + triples = [] + + for a, b, label in ast.literal_eval(back): + t = SentimentTriple( + t_start=a[0], + t_end=a[0] if len(a) == 1 else a[-1], + o_start=b[0], + o_end=b[0] if len(b) == 1 else b[-1], + label=label, + ) + triples.append(t) + + return cls( + tokens=tokens, triples=triples, id=0, pos=[], weight=1, is_labeled=True + ) + + def to_line_format(self) -> str: + # ([1], [4], 'POS') + # ([1,2], [4], 'POS') + triplets = [] + for t in self.triples: + parts = [] + for start, end in [(t.t_start, t.t_end), (t.o_start, t.o_end)]: + if start == end: + parts.append([start]) + else: + parts.append([start, end]) + parts.append(f"{t.label}") + triplets.append(tuple(parts)) + + line = " ".join(self.tokens) + "#### #### ####" + str(triplets) + "\n" + assert self.from_line_format(line).tokens == self.tokens + assert self.from_line_format(line).triples == self.triples + return line + + +class Data(BaseModel): + root: Path + data_split: SplitEnum + sentences: Optional[List[Sentence]] + full_path: str = "" + num_instances: int = -1 + opinion_offset: int = 3 # Refer: jet_o.py + is_labeled: bool = False + + def load(self): + if self.sentences is None: + path = self.root / f"{self.data_split}.txt" + if self.full_path: + path = self.full_path + + with open(path) as f: + self.sentences = [Sentence.from_line_format(line) for line in f] + + @classmethod + def load_from_full_path(cls, path: str): + data = cls(full_path=path, root=Path(path).parent, data_split=SplitEnum.train) + data.load() + return data + + def save_to_path(self, path: str): + assert self.sentences is not None + Path(path).parent.mkdir(exist_ok=True, parents=True) + with open(path, "w") as f: + for s in self.sentences: + f.write(s.to_line_format()) + + data = Data.load_from_full_path(path) + assert data.sentences is not None + for i, s in enumerate(data.sentences): + assert s.tokens == self.sentences[i].tokens + assert s.triples == self.sentences[i].triples + + def analyze_spans(self): + print("\nHow often is target closer to opinion than any invalid target?") + records = [] + for s in self.sentences: + valid_pairs = set([(a.opinion, a.target) for a in s.triples]) + for a in s.triples: + closest = None + for b in s.triples: + dist_a = abs(np.mean(a.opinion) - np.mean(a.target)) + dist_b = abs(np.mean(a.opinion) - np.mean(b.target)) + if dist_b <= dist_a and (a.opinion, b.target) not in valid_pairs: + closest = b.target + + spans = [a.opinion, a.target] + if closest is not None: + spans.append(closest) + + tokens = list(s.tokens) + for start, end in spans: + tokens[start] = "[" + tokens[start] + tokens[end] = tokens[end] + "]" + + start = min([s[0] for s in spans]) + end = max([s[1] for s in spans]) + tokens = tokens[start : end + 1] + + records.append(dict(is_closest=closest is None, text=" ".join(tokens))) + df = pd.DataFrame(records) + print(df["is_closest"].mean()) + print(df[~df["is_closest"]].head()) + + def analyze_joined_spans(self): + print("\nHow often are target/opinion spans joined?") + join_targets = 0 + join_opinions = 0 + total_targets = 0 + total_opinions = 0 + + for s in self.sentences: + targets = set([t.target for t in s.triples]) + opinions = set([t.opinion for t in s.triples]) + total_targets += len(targets) + total_opinions += len(opinions) + join_targets += count_joins(targets) + join_opinions += count_joins(opinions) + + print( + dict( + targets=join_targets / total_targets, + opinions=join_opinions / total_opinions, + ) + ) + + def analyze_tag_counts(self): + print("\nHow many tokens are target/opinion/none?") + record = [] + for s in self.sentences: + tags = [str(None) for _ in s.tokens] + for t in s.triples: + for i in range(t.o_start, t.o_end + 1): + tags[i] = "Opinion" + for i in range(t.t_start, t.t_end + 1): + tags[i] = "Target" + record.extend(tags) + print({k: v / len(record) for k, v in Counter(record).items()}) + + def analyze_span_distance(self): + print("\nHow far is the target/opinion from each other on average?") + distances = [] + for s in self.sentences: + for t in s.triples: + x_opinion = (t.o_start + t.o_end) / 2 + x_target = (t.t_start + t.t_end) / 2 + distances.append(abs(x_opinion - x_target)) + print(get_simple_stats(distances)) + + def analyze_opinion_labels(self): + print("\nFor opinion/target how often is it associated with only 1 polarity?") + for key in ["opinion", "target"]: + records = [] + for s in self.sentences: + term_to_labels: Dict[Tuple[int, int], List[LabelEnum]] = {} + for t in s.triples: + term_to_labels.setdefault(getattr(t, key), []).append(t.label) + records.extend([len(set(labels)) for labels in term_to_labels.values()]) + is_single_label = [n == 1 for n in records] + print( + dict( + key=key, + is_single_label=sum(is_single_label) / len(is_single_label), + stats=get_simple_stats(records), + ) + ) + + def analyze_tag_score(self): + print("\nIf have all target and opinion terms (unpaired), what is max f_score?") + pred = copy.deepcopy(self.sentences) + for s in pred: + target_to_label = {t.target: t.label for t in s.triples} + opinion_to_label = {t.opinion: t.label for t in s.triples} + s.triples = TripleHeuristic().run(opinion_to_label, target_to_label) + + analyzer = ResultAnalyzer() + analyzer.run(pred, gold=self.sentences, print_limit=0) + + def analyze_ner(self): + print("\n How many opinion/target per sentence?") + num_o, num_t = [], [] + for s in self.sentences: + opinions, targets = set(), set() + for t in s.triples: + opinions.add((t.o_start, t.o_end)) + targets.add((t.t_start, t.t_end)) + num_o.append(len(opinions)) + num_t.append(len(targets)) + print( + dict( + num_o=get_simple_stats(num_o), + num_t=get_simple_stats(num_t), + sentences=len(self.sentences), + ) + ) + + def analyze_direction(self): + print("\n For targets, is opinion offset always positive/negative/both?") + records = [] + for s in self.sentences: + span_to_offsets = {} + for t in s.triples: + off = np.mean(t.target) - np.mean(t.opinion) + span_to_offsets.setdefault(t.opinion, []).append(off) + for span, offsets in span_to_offsets.items(): + labels = [ + LabelEnum.positive if off > 0 else LabelEnum.negative + for off in offsets + ] + lab = labels[0] if len(set(labels)) == 1 else LabelEnum.neutral + records.append( + dict( + span=" ".join(s.tokens[span[0] : span[1] + 1]), + text=s.as_text(), + offsets=lab, + ) + ) + df = pd.DataFrame(records) + print(df["offsets"].value_counts(normalize=True)) + df = df[df["offsets"] == LabelEnum.neutral].drop(columns=["offsets"]) + with pd.option_context("display.max_colwidth", 999): + print(df.head()) + + def analyze(self): + triples = [t for s in self.sentences for t in s.triples] + info = dict( + root=self.root, + sentences=len(self.sentences), + sentiments=Counter([t.label for t in triples]), + target_lengths=get_simple_stats( + [abs(t.t_start - t.t_end) + 1 for t in triples] + ), + opinion_lengths=get_simple_stats( + [abs(t.o_start - t.o_end) + 1 for t in triples] + ), + sentence_lengths=get_simple_stats([len(s.tokens) for s in self.sentences]), + ) + for k, v in info.items(): + print(k, v) + + self.analyze_direction() + self.analyze_ner() + self.analyze_spans() + self.analyze_joined_spans() + self.analyze_tag_counts() + self.analyze_span_distance() + self.analyze_opinion_labels() + self.analyze_tag_score() + print("#" * 80) + + +def test_save_to_path(path: str = "aste/data/triplet_data/14lap/train.txt"): + print("\nEnsure that Data.save_to_path works properly") + path_temp = "temp.txt" + data = Data.load_from_full_path(path) + data.save_to_path(path_temp) + print("\nSamples") + with open(path_temp) as f: + for line in f.readlines()[:5]: + print(line) + os.remove(path_temp) + + +def merge_data(items: List[Data]) -> Data: + merged = Data(root=Path(), data_split=items[0].data_split, sentences=[]) + for data in items: + data.load() + merged.sentences.extend(data.sentences) + return merged + + +class Result(BaseModel): + num_sentences: int + num_pred: int = 0 + num_gold: int = 0 + num_correct: int = 0 + num_start_correct: int = 0 + num_start_end_correct: int = 0 + num_opinion_correct: int = 0 + num_target_correct: int = 0 + num_span_overlap: int = 0 + precision: float = 0.0 + recall: float = 0.0 + f_score: float = 0.0 + + +class ResultAnalyzer(BaseModel): + @staticmethod + def check_overlap(a_start: int, a_end: int, b_start: int, b_end: int) -> bool: + return (b_start <= a_start <= b_end) or (b_start <= a_end <= b_end) + + @staticmethod + def run_sentence(pred: Sentence, gold: Sentence): + assert pred.tokens == gold.tokens + triples_gold = set([t.as_text(gold.tokens) for t in gold.triples]) + triples_pred = set([t.as_text(pred.tokens) for t in pred.triples]) + tp = triples_pred.intersection(triples_gold) + fp = triples_pred.difference(triples_gold) + fn = triples_gold.difference(triples_pred) + if fp or fn: + print(dict(gold=gold.as_text())) + print(dict(pred=pred.as_text())) + print(dict(tp=tp)) + print(dict(fp=fp)) + print(dict(fn=fn)) + print("#" * 80) + + @staticmethod + def analyze_labels(pred: List[Sentence], gold: List[Sentence]): + y_pred = [] + y_gold = [] + for i in range(len(pred)): + for p in pred[i].triples: + for g in gold[i].triples: + if (p.opinion, p.target) == (g.opinion, g.target): + y_pred.append(str(p.label)) + y_gold.append(str(g.label)) + + print(dict(num_span_correct=len(y_pred))) + if y_pred: + print(classification_report(y_gold, y_pred)) + + @staticmethod + def analyze_spans(pred: List[Sentence], gold: List[Sentence]): + num_triples_gold, triples_found_o, triples_found_t = 0, set(), set() + for label in [LabelEnum.opinion, LabelEnum.target]: + num_correct, num_pred, num_gold = 0, 0, 0 + is_target = {LabelEnum.opinion: False, LabelEnum.target: True}[label] + for i, (p, g) in enumerate(zip(pred, gold)): + spans_gold = set(g.spans if g.spans else g.extract_spans()) + spans_pred = set(p.spans if p.spans else p.extract_spans()) + spans_gold = set([s for s in spans_gold if s[-1] == label]) + spans_pred = set([s for s in spans_pred if s[-1] == label]) + + num_gold += len(spans_gold) + num_pred += len(spans_pred) + num_correct += len(spans_gold.intersection(spans_pred)) + + for t in g.triples: + num_triples_gold += 1 + span = (t.target if is_target else t.opinion) + (label,) + if span in spans_pred: + t_unique = (i,) + tuple(t.dict().items()) + if is_target: + triples_found_t.add(t_unique) + else: + triples_found_o.add(t_unique) + + if num_correct and num_pred and num_gold: + p = round(num_correct / num_pred, ndigits=4) + r = round(num_correct / num_gold, ndigits=4) + f = round(2 * p * r / (p + r), ndigits=4) + info = dict(label=label, p=p, r=r, f=f) + print(json.dumps(info, indent=2)) + + assert num_triples_gold % 2 == 0 # Was double-counted above + num_triples_gold = num_triples_gold // 2 + num_triples_pred_ceiling = len(triples_found_o.intersection(triples_found_t)) + triples_pred_recall_ceiling = num_triples_pred_ceiling / num_triples_gold + print("\n What is the upper bound for RE from predicted O & T?") + print(dict(recall=round(triples_pred_recall_ceiling, ndigits=4))) + + @classmethod + def run(cls, pred: List[Sentence], gold: List[Sentence], print_limit=16): + assert len(pred) == len(gold) + cls.analyze_labels(pred, gold) + + r = Result(num_sentences=len(pred)) + for i in range(len(pred)): + if i < print_limit: + cls.run_sentence(pred[i], gold[i]) + r.num_pred += len(pred[i].triples) + r.num_gold += len(gold[i].triples) + for p in pred[i].triples: + for g in gold[i].triples: + if p.dict() == g.dict(): + r.num_correct += 1 + if (p.o_start, p.t_start) == (g.o_start, g.t_start): + r.num_start_correct += 1 + if (p.opinion, p.target) == (g.opinion, g.target): + r.num_start_end_correct += 1 + if p.opinion == g.opinion: + r.num_opinion_correct += 1 + if p.target == g.target: + r.num_target_correct += 1 + if cls.check_overlap(*p.opinion, *g.opinion) and cls.check_overlap( + *p.target, *g.target + ): + r.num_span_overlap += 1 + + e = 1e-9 + r.precision = round(r.num_correct / (r.num_pred + e), 4) + r.recall = round(r.num_correct / (r.num_gold + e), 4) + r.f_score = round(2 * r.precision * r.recall / (r.precision + r.recall + e), 3) + print(r.json(indent=2)) + cls.analyze_spans(pred, gold) + + +def test_merge(root="aste/data/triplet_data"): + unmerged = [Data(root=p, data_split=SplitEnum.train) for p in Path(root).iterdir()] + data = merge_data(unmerged) + data.analyze() + + +if __name__ == "__main__": + Fire() diff --git a/aste/utils.py b/aste/utils.py new file mode 100644 index 0000000..db31806 --- /dev/null +++ b/aste/utils.py @@ -0,0 +1,175 @@ +import copy +import hashlib +import pickle +import subprocess +import time +from pathlib import Path +from typing import List, Set, Tuple, Union + +from fire import Fire +from pydantic import BaseModel + + +class Shell(BaseModel): + verbose: bool = True + + @classmethod + def format_kwargs(cls, **kwargs) -> str: + outputs = [] + for k, v in kwargs.items(): + k = k.replace("_", "-") + k = f"--{k}" + outputs.extend([k, str(v)]) + return " ".join(outputs) + + def run_command(self, command: str) -> str: + # Continuously print outputs for long-running commands + # Refer: https://fabianlee.org/2019/09/15/python-getting-live-output-from-subprocess-using-poll/ + print(dict(command=command)) + process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + outputs = [] + + while True: + if process.poll() is not None: + break + o = process.stdout.readline().decode() + if o: + outputs.append(o) + if self.verbose: + print(o.strip()) + + return "".join(outputs) + + def run(self, command: str, *args, **kwargs) -> str: + args = [str(a) for a in args] + command = " ".join([command] + args + [self.format_kwargs(**kwargs)]) + return self.run_command(command) + + +def hash_text(x: str) -> str: + return hashlib.md5(x.encode()).hexdigest() + + +class Timer(BaseModel): + name: str = "" + start: float = 0.0 + + def __enter__(self): + self.start = time.time() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + duration = round(time.time() - self.start, 3) + print(f"Timer {self.name}: {duration}s") + + +class PickleSaver(BaseModel): + path: Path + + def dump(self, obj): + if not self.path.parent.exists(): + self.path.parent.mkdir(exist_ok=True) + with open(self.path, "wb") as f: + pickle.dump(obj, f) + + def load(self): + with Timer(name=str(self.path)): + with open(self.path, "rb") as f: + return pickle.load(f) + + +class FlexiModel(BaseModel): + class Config: + arbitrary_types_allowed = True + + +def get_simple_stats(numbers: List[Union[int, float]]): + return dict( + min=min(numbers), + max=max(numbers), + avg=sum(numbers) / len(numbers), + ) + + +def count_joins(spans: Set[Tuple[int, int]]) -> int: + count = 0 + for a_start, a_end in spans: + for b_start, b_end in spans: + if (a_start, a_end) == (b_start, b_end): + continue + + if b_start <= a_start <= b_end + 1 or b_start - 1 <= a_end <= b_end: + count += 1 + return count // 2 + + +def update_nested_dict(d: dict, k: str, v, i=0, sep="__"): + d = copy.deepcopy(d) + keys = k.split(sep) + assert keys[i] in d.keys(), str(dict(keys=keys, d=d, i=i)) + if i == len(keys) - 1: + orig = d[keys[i]] + if v != orig: + print(dict(updated_key=k, new_value=v, orig=orig)) + d[keys[i]] = v + else: + d[keys[i]] = update_nested_dict(d=d[keys[i]], k=k, v=v, i=i + 1) + return d + + +def test_update_nested_dict(): + d = dict(top=dict(middle_a=dict(last=1), middle_b=0)) + print(update_nested_dict(d, k="top__middle_b", v=-1)) + print(update_nested_dict(d, k="top__middle_a__last", v=-1)) + print(update_nested_dict(d, k="top__middle_a__last", v=1)) + + +def clean_up_triplet_data(path: str): + outputs = [] + with open(path) as f: + for line in f: + sep = "####" + text, tags_t, tags_o, triplets = line.split(sep) + outputs.append(sep.join([text, " ", " ", triplets])) + + with open(path, "w") as f: + f.write("".join(outputs)) + + +def clean_up_many(pattern: str = "data/triplet_data/*/*.txt"): + for path in sorted(Path().glob(pattern)): + print(path) + clean_up_triplet_data(str(path)) + + +def merge_data( + folders_in: List[str] = [ + "aste/data/triplet_data/14res/", + "aste/data/triplet_data/15res/", + "aste/data/triplet_data/16res/", + ], + folder_out: str = "aste/data/triplet_data/res_all/", +): + for name in ["train.txt", "dev.txt", "test.txt"]: + outputs = [] + for folder in folders_in: + path = Path(folder) / name + with open(path) as f: + for line in f: + assert line.endswith("\n") + outputs.append(line) + + path_out = Path(folder_out) / name + path_out.parent.mkdir(exist_ok=True, parents=True) + with open(path_out, "w") as f: + f.write("".join(outputs)) + + +def safe_divide(a: float, b: float) -> float: + if a == 0 or b == 0: + return 0 + return a / b + + +if __name__ == "__main__": + Fire() diff --git a/aste/wrapper.py b/aste/wrapper.py new file mode 100644 index 0000000..baeeeb1 --- /dev/null +++ b/aste/wrapper.py @@ -0,0 +1,268 @@ +import json +import os +import shutil +import sys +from argparse import Namespace +from pathlib import Path +from typing import List, Tuple, Optional + +from allennlp.commands.predict import _predict +from allennlp.commands.train import train_model +from allennlp.common import Params +from fire import Fire +from pydantic import BaseModel +from tqdm import tqdm + +from .data_utils import Data, SentimentTriple, SplitEnum, Sentence, LabelEnum +from .utils import safe_divide + + +class SpanModelDocument(BaseModel): + sentences: List[List[str]] + ner: List[List[Tuple[int, int, str]]] + relations: List[List[Tuple[int, int, int, int, str]]] + doc_key: str + + @property + def is_valid(self) -> bool: + return len(set(map(len, [self.sentences, self.ner, self.relations]))) == 1 + + @classmethod + def from_sentence(cls, x: Sentence): + ner: List[Tuple[int, int, str]] = [] + for t in x.triples: + ner.append((t.o_start, t.o_end, LabelEnum.opinion)) + ner.append((t.t_start, t.t_end, LabelEnum.target)) + ner = sorted(set(ner), key=lambda n: n[0]) + relations = [ + (t.o_start, t.o_end, t.t_start, t.t_end, t.label) for t in x.triples + ] + return cls( + sentences=[x.tokens], + ner=[ner], + relations=[relations], + doc_key=str(x.id), + ) + + +class SpanModelPrediction(SpanModelDocument): + predicted_ner: List[List[Tuple[int, int, LabelEnum, float, float]]] = [ + [] + ] # If loss_weights["ner"] == 0.0 + predicted_relations: List[List[Tuple[int, int, int, int, LabelEnum, float, float]]] + + def to_sentence(self) -> Sentence: + for lst in [self.sentences, self.predicted_ner, self.predicted_relations]: + assert len(lst) == 1 + + triples = [ + SentimentTriple(o_start=os, o_end=oe, t_start=ts, t_end=te, label=label) + for os, oe, ts, te, label, value, prob in self.predicted_relations[0] + ] + return Sentence( + id=int(self.doc_key), + tokens=self.sentences[0], + pos=[], + weight=1, + is_labeled=False, + triples=triples, + spans=[lst[:3] for lst in self.predicted_ner[0]], + ) + + +class SpanModelData(BaseModel): + root: Path + data_split: SplitEnum + documents: Optional[List[SpanModelDocument]] + + @classmethod + def read(cls, path: Path) -> List[SpanModelDocument]: + docs = [] + with open(path) as f: + for line in f: + line = line.strip() + raw: dict = json.loads(line) + docs.append(SpanModelDocument(**raw)) + return docs + + def load(self): + if self.documents is None: + path = self.root / f"{self.data_split}.json" + self.documents = self.read(path) + + def dump(self, path: Path, sep="\n"): + for d in self.documents: + assert d.is_valid + with open(path, "w") as f: + f.write(sep.join([d.json() for d in self.documents])) + assert all( + [a.dict() == b.dict() for a, b in zip(self.documents, self.read(path))] + ) + + @classmethod + def from_data(cls, x: Data): + data = cls(root=x.root, data_split=x.data_split) + data.documents = [SpanModelDocument.from_sentence(s) for s in x.sentences] + return data + + +class SpanModel(BaseModel): + save_dir: str + random_seed: int + path_config_base: str = "training_config/config.json" + + def save_temp_data(self, path_in: str, name: str, is_test: bool = False) -> Path: + path_temp = Path(self.save_dir) / "temp_data" / f"{name}.json" + path_temp = path_temp.resolve() + path_temp.parent.mkdir(exist_ok=True, parents=True) + data = Data.load_from_full_path(path_in) + + if is_test: + # SpanModel error if s.triples is empty list + assert data.sentences is not None + for s in data.sentences: + s.triples = [SentimentTriple.make_dummy()] + + span_data = SpanModelData.from_data(data) + span_data.dump(path_temp) + return path_temp + + def fit(self, path_train: str, path_dev: str): + weights_dir = Path(self.save_dir) / "weights" + weights_dir.mkdir(exist_ok=True, parents=True) + print(dict(weights_dir=weights_dir)) + + params = Params.from_file( + self.path_config_base, + params_overrides=dict( + random_seed=self.random_seed, + numpy_seed=self.random_seed, + pytorch_seed=self.random_seed, + train_data_path=str(self.save_temp_data(path_train, "train")), + validation_data_path=str(self.save_temp_data(path_dev, "dev")), + test_data_path=str(self.save_temp_data(path_dev, "dev")), + ), + ) + + # Register custom modules + sys.path.append(".") + from span_model.data.dataset_readers.span_model import SpanModelReader + + assert SpanModelReader is not None + train_model(params, serialization_dir=str(weights_dir)) + + def predict(self, path_in: str, path_out: str): + path_model = Path(self.save_dir) / "weights" / "model.tar.gz" + path_temp_in = self.save_temp_data(path_in, "pred_in", is_test=True) + path_temp_out = Path(self.save_dir) / "temp_data" / "pred_out.json" + if path_temp_out.exists(): + os.remove(path_temp_out) + + args = Namespace( + archive_file=str(path_model), + input_file=str(path_temp_in), + output_file=str(path_temp_out), + weights_file="", + batch_size=1, + silent=True, + cuda_device=0, + use_dataset_reader=True, + dataset_reader_choice="validation", + overrides="", + predictor="span_model", + file_friendly_logging=False, + ) + + # Register custom modules + sys.path.append(".") + from span_model.data.dataset_readers.span_model import SpanModelReader + from span_model.predictors.span_model import SpanModelPredictor + + assert SpanModelReader is not None + assert SpanModelPredictor is not None + _predict(args) + + with open(path_temp_out) as f: + preds = [SpanModelPrediction(**json.loads(line.strip())) for line in f] + data = Data( + root=Path(), + data_split=SplitEnum.test, + sentences=[p.to_sentence() for p in preds], + ) + data.save_to_path(path_out) + + @classmethod + def score(cls, path_pred: str, path_gold: str) -> dict: + pred = Data.load_from_full_path(path_pred) + gold = Data.load_from_full_path(path_gold) + assert pred.sentences is not None + assert gold.sentences is not None + assert len(pred.sentences) == len(gold.sentences) + num_pred = 0 + num_gold = 0 + num_correct = 0 + + for i in range(len(gold.sentences)): + num_pred += len(pred.sentences[i].triples) + num_gold += len(gold.sentences[i].triples) + for p in pred.sentences[i].triples: + for g in gold.sentences[i].triples: + if p.dict() == g.dict(): + num_correct += 1 + + precision = safe_divide(num_correct, num_pred) + recall = safe_divide(num_correct, num_gold) + + info = dict( + path_pred=path_pred, + path_gold=path_gold, + precision=precision, + recall=recall, + score=safe_divide(2 * precision * recall, precision + recall), + ) + return info + + +def run_score(path_pred: str, path_gold: str) -> dict: + return SpanModel.score(path_pred, path_gold) + + +def run_train(path_train: str, path_dev: str, save_dir: str, random_seed: int): + print(dict(run_train=locals())) + if Path(save_dir).exists(): + return + + model = SpanModel(save_dir=save_dir, random_seed=random_seed) + model.fit(path_train, path_dev) + + +def run_train_many(save_dir_template: str, random_seeds: List[int], **kwargs): + for seed in tqdm(random_seeds): + save_dir = save_dir_template.format(seed) + run_train(save_dir=save_dir, random_seed=seed, **kwargs) + + +def run_eval(path_test: str, save_dir: str): + print(dict(run_eval=locals())) + model = SpanModel(save_dir=save_dir, random_seed=0) + path_pred = str(Path(save_dir) / "pred.txt") + model.predict(path_test, path_pred) + results = model.score(path_pred, path_test) + print(results) + return results + + +def run_eval_many(save_dir_template: str, random_seeds: List[int], **kwargs): + results = [] + for seed in tqdm(random_seeds): + save_dir = save_dir_template.format(seed) + results.append(run_eval(save_dir=save_dir, **kwargs)) + + precision = sum(r["precision"] for r in results) / len(random_seeds) + recall = sum(r["recall"] for r in results) / len(random_seeds) + score = safe_divide(2 * precision * recall, precision + recall) + print(dict(precision=precision, recall=recall, score=score)) + + +if __name__ == "__main__": + Fire() diff --git a/dataset/14lap.csv b/dataset/14lap.csv new file mode 100644 index 0000000..e3bbad3 --- /dev/null +++ b/dataset/14lap.csv @@ -0,0 +1,328 @@ +"Boot time is super fast , around anywhere from 35 seconds to 1 minute ." +tech support would not fix the problem unless I bought your plan for $ 150 plus . +Set up was easy . +Did not enjoy the new Windows 8 and touchscreen functions . +"Other than not being a fan of click pads ( industry standard these days ) and the lousy internal speakers , it 's hard for me to find things about this notebook I do n't like , especially considering the $ 350 price tag ." +"It 's fast , light , and simple to use ." +"Works well , and I am extremely happy to be back to an apple OS ." +Sure it 's not light and slim but the features make up for it 100 % . +"I am pleased with the fast log on , speedy WiFi connection and the long battery life ( > 6 hrs ) ." +The Apple engineers have not yet discovered the delete key . +Made interneting ( part of my business ) very difficult to maintain . +"Luckily , for all of us contemplating the decision , the Mac Mini is priced just right ." +"Only problem that I had was that the track pad was not very good for me , I only had a problem once or twice with it , But probably my computer was a bit defective ." +It is super fast and has outstanding graphics . +But the mountain lion is just too slow . +Strong build though which really adds to its durability . +The battery life is excellent -- 6-7 hours without charging . +I 've had my computer for 2 weeks already and it works perfectly . +And I may be the only one but I am really liking Windows 8 . +The baterry is very longer . +Its size is ideal and the weight is acceptable . +I can say that I am fully satisfied with the performance that the computer has supplied . +It has so much more speed and the screen is very sharp . +Everything I wanted and everything I needed and the price was great ! +It 's not inexpensive but the Hardware performance is impressive for a computer this small . +"This thing is awesome , everything always works , everything is always easy to set up , everything is compatible , its literally everything I could ask for ." +Keyboard responds well to presses . +"Lastly , Windows 8 is annoying ." +Everything is so easy and intuitive to setup or configure . +Biggest complaint is Windows 8 . +Only 2 usb ports ... seems kind of ... limited . +It has all the expected features and more +plus a wide screen and more than roomy keyboard . +Amazing Performance for anything I throw at it . +The receiver was full of superlatives for the quality and performance . +I was extremely happy with the OS itself . +The new MBP offers great portability and gives us confidence that we are not going to need to purchase a new laptop in 18 months . +"The criticism has waned , and now I 'd be the first to recommend an Air for truly portable computing ." +"MS Office 2011 for Mac is wonderful , well worth it ." +But the performance of Mac Mini is a huge disappointment . +They do n't just look good ; they deliver excellent performance . +I have had it over a year now with out a Glitch of any kind..I love the lit up keys and screen display ... this thing is Fast and clear as can be . +The Mountain Lion OS is not hard to figure out if you are familiar with Microsoft Windows . +"However , I can refute that OSX is `` FAST '' ." +Enjoy using Microsoft Office ! +Incredible graphics and brilliant colors . +Built-in apps are purely amazing . +From the speed to the multi touch gestures this operating system beats Windows easily . +I really like the size and I 'm a fan of the ACERS . +I opted for the SquareTrade 3-Year Computer Accidental Protection Warranty ( $ 1500-2000 ) which also support `` accidents '' like drops and spills that are NOT covered by AppleCare . +It 's light and easy to transport . +Once you get past learning how to use the poorly designed Windows 8 Set-Up you may feel frustrated . +The aluminum body sure makes it stand out . +"It is very easy to integrate bluetooth devices , and USB devices are recognized almost instantly ." +And the fact that Apple is driving the 13 '' RMBP with the Intel4000 graphic chip seems underpowered ( to me . +Apple removed the DVD drive Firewire port ( will work with adapter ) and put the SDXC slot in a silly position on the back . +The durability of the laptop will make it worth the money . +Well designed and fast . +"But I was completely wrong , this computer is UNBELIEVABLE amazing and easy to use ." +Exactly as posted plus a great value . +The specs are pretty good too . +"Apple is unmatched in product quality , aesthetics , craftmanship , and customer service ." +It is a great size and amazing windows 8 included ! +I do not like too much Windows 8 . +Startup times are incredibly long : over two minutes . +Also stunning colors and speedy +great price free shipping what else can i ask for ! ! +This mouse is terrific . +It is really thick around the battery . +And windows 7 works like a charm . +": ) Great product , great price , great delivery , and great service ." +: ] It arrived so fast and customer service was great . +tried windows 8 and hated it ! ! ! +Set up was a breeze . +But I do NOT like Win8 . +"I had the same reasons as most PC users : the price , the overbearing restrictions of OSX and lack of support for games ." +"I wanted it for it 's mobility and man , this little bad boy is very nice ." +I found the mini to be : Exceptionally easy to set up +The sound is nice and loud ; I do n't have any problems with hearing anything . +"It is very slim , the track pad is very much impressed with me ." +The settings are not user-friendly either . +Thank goodness for OpenOffice ! +"Awesome form factor , great battery life , wonderful UX ." +i love the keyboard and the screen . +"However , there are MAJOR issues with the touchpad which render the device nearly useless ." +I 've already upgraded o Mavericks and I am impressed with everything about this computer . +Not as fast as I would have expect for an i5 . +thanks for great service and shipping ! +"The performance seems quite good , and built-in applications like iPhoto work great with my phone and camera ." +I did swap out the hard drive for a Samsung 830 SSD which I highly recommend . +"Yes , that 's a good thing , but it 's made from aluminum that scratches easily ." +I was also informed that the components of the Mac Book were dirty . +"the hardware problems have been so bad , i ca n't wait till it completely dies in 3 years , TOPS !" +It 's so nice that the battery last so long and that this machine has the snow lion ! +"it 's exactly what i wanted , and it has all the new features and whatnot ." +"It feels cheap , the keyboard is not very sensitive ." +"Though please note that sometimes it crashes , and the sound quality isnt superb ." +It is very easy to navigate even for a novice . +"Does everything I need it to , has a wonderful battery life and I could n't be happier ." +Great Performance and Quality . +"One more thing , this mac does NOT come with restore disks and I am not sure if you can make them direct from the mac like you can with newer PC 's , also the charging cables are made of the same cheap material as the iPhone/iPod touch cables ." +The new os is great on my macbook pro ! +"I have experienced no problems , works as anticipated ." +System is running great . +Easy to customize setting and even create your own bookmarks . +"it has all the features that we expected and the price was good , working well so far ." +The new operating system makes this computer into a super iPad . +Easy to set up and go ! +I ca n't believe how quiet the hard drive is and how quick this thing boots up . +It 's just what we were looking for and it works great . +It 's so quick and responsive that it makes working / surfing on a computer so much more pleasurable ! +"It works fine , and all the software seems to run pretty well ." +"I wanted a computer that was quite , fast , and that had overall great performance ." +"Harddrive was in poor condition , had to replace it ." +The on/off switch is a bit obscure in the rear corner . +My only complaint is the total lack of instructions that come with the mac mini . +"The only task that this computer would not be good enough for would be gaming , otherwise the integrated Intel 4000 graphics work well for other tasks ." +"I use it mostly for content creation ( Audio , video , photo editing ) and its reliable ." +Screen is bright and gorgeous . +"It is robust , with a friendly use as all Apple products ." +It is fast and easy to use . +And the fact that it comes with an i5 processor definitely speeds things up +I have been PC for years but this computer is intuitive and its built in features are a great help +"Nice screen , keyboard works great !" +I was amazed at how fast the delivery was . +The memory was gone and it was not able to be used . +It works great and I am so happy I bought it . +"I like the design and ease of use with the keyboard , plenty of ports ." +it definitely beats my old mac and the service was great . +Web browsing is very quick with Safari browser . +I like the lighted screen at night . +It is really easy to use and it is quick to start up . +I 've lived with the crashes and slow operation and restarts . +USB3 Peripherals are noticably less expensive than the ThunderBolt ones . +"It 's fast , light , and is perfect for media editing , which is mostly why I bought it in the first place ." +"The battery lasts as advertised ( give or take 15-20 minutes ) , and the entire user experience is very elegant ." +Thanks for the fast shipment and great price . +"! Excellent performance , usability , presentation and time response ." +The smaller size was a bonus because of space restrictions . +I blame the Mac OS . +I like the operating system . +I love the form factor . +It 's fast at loading the internet . +So much faster and sleeker looking . +"Unfortunately , it runs XP and Microsoft is dropping support next April ." +"First off , I really do like my MBP ... once used to the OS it is pretty easy to get around , and the overall build is great ... eg the keyboard is one of the best to type on ." +It is made of such solid construction and since I have never had a Mac using my iPhone helped me get used to the system a bit . +Very nice unibody construction . +"This Macbook Pro is fast , powerful , and runs super quiet and cool ." +It 's ok but does n't have a disk drive which I did n't know until after I bought it . +"There is no HDMI receptacle , nor is there an SD card slot located anywhere on the device ." +It came in brand new and works perfectly . +"It should n't happen like that , I do n't have any design app open or anything ." +MY TRACKPAD IS NOT WORKING . +"It looks and feels solid , with a flawless finish ." +Price was higher when purchased on MAC when compared to price showing on PC when I bought this product . +Then the system would many times not power down without a forced power-off . +The configuration is perfect for my needs . +and the speakers is the worst ever . +"Its the best , its got the looks , super easy to use and love all you can do with the trackpad ! .." +Web surfuring is smooth and seamless . +I 'm overall pleased with the interface and the portability of this product . +"This item is a beautiful piece , it works well , it is easy to carry and handle ." +"It was also suffering from hardware ( keyboard ) issues , relatively slow performance and shortening battery lifetime ." +"Runs good and does the job , ca n't complain about that !" +It 's silent and has a very small footprint on my desk . +The exterior is absolutely gorgeous . +"It has a very high performance , just for what I needed for ." +Apple is aware of this issue and this is either old stock or a defective design involving the intel 4000 graphics chipset . +"I just bought the new MacBook Pro , the 13 '' model , and I ca n't believe Apple keeps making the same mistake with regard to USB ports ." +It is the perfect size and speed for me . +THE CUSTOMER SERVICE IS TERRIFIC ! ! +"My last laptop was a 17 '' ASUS gaming machine , which performed admirably , but having since built my own desktop and really settling into the college life , I found myself wanting something smaller and less cumbersome , not to mention that the ASUS had been slowly developing problems ever since I bought it about 4 years ago ." +"However , it did not have any scratches , ZERO battery cycle count ( pretty surprised ) , and all the hardware seemed to be working perfectly ." +And as for all the fancy finger swipes -- I just gave up and attached a mouse . +"I needed a laptop with big storage , a nice screen and fast so I can photoshop without any problem ." +I like coming back to Mac OS but this laptop is lacking in speaker quality compared to my $ 400 old HP laptop . +Shipped very quickly and safely . +The thunderbolt port is awesome ! +The performance is definitely superior to any computer I 've ever put my hands on . +It 's great for streaming video and other entertainment uses . +I like the design and its features but there are somethings I think needs to be improved . +There were small problems with Mac office . +I ordered my 2012 mac mini after being disappointed with spec of the new 27 '' Imacs . +"Its fast , easy to use and it looks great ." +"Performance is much much better on the Pro , especially if you install an SSD on it ." +"Note , however , that any existing MagSafe accessories you have will not work with the MagSafe 2 connection ." +"The only thing I dislike is the touchpad , alot of the times its unresponsive and does things I dont want it too , I would recommend using a mouse with it ." +"The Mac mini is about 8x smaller than my old computer which is a huge bonus and runs very quiet , actually the fans are n't audible unlike my old pc" +I thought the transition would be difficult at best and would take some time to fully familiarize myself with the new Mac ecosystem . +It 's absolutely wonderful and worth the price ! +I am please with the products ease of use ; out of the box ready ; appearance and functionality . +Perfect for all my graphic design classes I 'm taking this year in college : - ) +I will not be using that slot again . +"The OS is fast and fluid , everything is organized and it 's just beautiful ." +They are simpler to use . +! so nice .. stable .. fast .. now i got my SSD ! +I love the quick start up . +You just can not beat the functionality of an Apple device . +Yet my mac continues to function properly . +Graphics are much improved . +"Here are the things that made me confident with my purchase : Build Quality - Seriously , you ca n't beat a unibody construction ." +It provides much more flexibility for connectivity . +Mac tutorials do help . +The technical support was not helpful as well . +I got the new adapter and there was no change . +"Logic board utterly fried , cried , and laid down and died ." +The sound was crappy even when you turn up the volume still the same results . +OSX Lion is a great performer..extremely fast and reliable . +"Having heard from friends and family about how reliable a Mac product is , I never expected to have an application crash within the first month , but I did ." +The Macbook pro 's physical form is wonderful . +The Mini 's body has n't changed since late 2010- and for a good reason . +The unibody construction really does feel lot more solid than Apple 's previous laptops . +3D rendering slows it down considerably . +"fast , great screen , beautiful apps for a laptop ; priced at 1100 on the apple website ; amazon had it for 1098+ tax - plus i had a 10 % off coupon from amazon-cost me 998 plus tax- 1070- OTD !" +All the ports are much needed since this is my main computer . +"The Like New condition of the iMac MC309LL/A on Amazon is at $ 900+ level only , and it is a Quad-Core 2.5 GHz CPU ( similar to the $ 799 Mini ) , with Radeon HD 6750M 512MB graphic card ( this mini is integrated Intel 4000 card ) , and it even comes with wireless Apple Keyboard and Mouse , all put together in neat and nice package ." +Put a cover on it and is a little better but that is my only complaint . +Within a few hours I was using the gestures unconsciously . +This mac does come with an extender cable and I 'm using mine right now hoping the cable will stay nice for the many years I plan on using this mac . +The 2.9ghz dual-core i7 chip really out does itself . +It is pretty snappy and starts up in about 30 seconds which is good enough for me . +Not sure on Windows 8 . +My one complaint is that there was no internal CD drive . +This newer netbook has no hard drive or network lights . +Not too expense and has enough storage for most users and many ports . +The audio volume is quite low and virtually unusable in a room with any background activity . +It is lightweight and the perfect size to carry to class . +The MBP is beautiful has many wonderful capabilities . +"I thought that it will be fine , if i do some settings ." +Runs very smoothly . +Boot-up slowed significantly after all Windows updates were installed . +"It was important that it was powerful enough to do all of the tasks he needed on the internet , word processing , graphic design and gaming ." +"I like the Mini Mac it was easy to setup and install , but I am learning as I go and could use a tutorial to learn how to use some of the features I was use to on the PC especially the right mouse click menu ." +Runs real quick . +"Since the machine 's slim profile is critical to me , that was a problem ." +"WiFi capability , disk drive and multiple USB ports to connect scale and printers was all that was required ." +"The SD card reader is slightly recessed and upside down ( the nail slot on the card can not be accessed ) , if this was a self ejecting slot this would not be an issue , but its not ." +"Soft touch , anodized aluminum with laser cut precision and no flaws ." +"Simple details , crafted aluminium and real glass make this laptop blow away the other plastic ridden , bulky sticker filled laptops ." +First of all yes this is a mac and it has that nice brushed aluminum . +No HDMI port . +Customization on mac is impossible . +Plus two finger clicking as a replacement for the right click button is surprisingly intuitive . +The SuperDrive is quiet . +"The battery was completely dead , in fact it had grown about a quarter inch thick lump on the underside ." +if yo like practicality this is the laptop for you . +The OS is great . +"CONS : Price is a bit ridiculous , kinda heavy ." +"Which it did not have , only 3 USB 2 ports ." +No startup disk was not included but that may be my fault . +It is very fast and has everything that I need except for a word program . +Needs a CD/DVD drive and a bigger power switch . +My laptop with Windows 7 crashed and I did not want Windows 8 . +Easy to install also small to leave anywhere at your bedroom also very easy to configure for ADSl cable or wifi . +Nice packing . +"I switched to this because I wanted something different , even though I miss windows ." +"Apple no longer includes iDVD with the computer and furthermore , Apple does n't even offer it anymore !" +"I also wanted Windows 7 , which this one has ." +"At first , I feel a little bit uncomfortable in using the Mac system ." +It just works out of the box and you have a lot of cool software included with the OS . +its as advertised on here ... .. it works great and is not a waste of money ! +Premium price for the OS more than anything else . +"I was a little concerned about the touch pad based on reviews , but I 've found it fine to work with ." +"However , the experience was great since the OS does not become unstable and the application will simply shutdown and reopen ." +The battery is not as shown in the product photos . +Shipping was quick and product described was the product sent and so much more ... +the retina display display make pictures i took years ago jaw dropping . +The Mac Mini is probably the simplest example of compact computing out there . +"Additionally , there is barely a ventilation system in the computer , and even the simple activity of watching videos let alone playing steam games causes the laptop to get very very hot , and in fact impossible to keep on lap ." +"Chatting with Acer support , I was advised the problem was corrupted operating system files ." +It 's been a couple weeks since the purchase and I 'm struggle with finding the correct keys ( but that was expected ) . +"Many people complain about the new OS , and it 's urgent for Apple to fix it asap !" +Now that I have upgraded to Lion I am much happier about MAC OS and have just bought an iMac for office . +User upgradeable RAM and HDD . +But I wanted the Pro for the CD/DVD player . +I was a little worry at first because I do n't have a lot of experience with os.x and windows has always been second nature to me after many years of using windows . +With the softwares supporting the use of other OS makes it much better . +"I was considering buying the Air , but in reality , this one has a more powerful performance and seems much more convenient , even though it 's about .20 inch thicker and 2 lbs heavier ." +"At home and the office it gets plugged into an external 24 '' LCD screen , so built in screen size is not terribly important ." +Just beware no DVD slot so when I went to install software I had on CD I could n't . +No Cd Rom in the new version there 's no way I 'm spending that kind of money on something has less features than the older version . +the volume is really low to low for a laptopwas not expectin t volume to be so lowan i hate that about this computer +and its not hard to accidentally bang it against something so i recommend getting a case to protect it . +I got this at an amazing price from Amazon and it arrived just in time . +"Every time I log into the system after a few hours , there is this endlessly frustrating process that I have to go through ." +"Put a SSD and use a 21 '' LED screen , this set up is silky smooth !" +"The case is now slightly larger than the previous generation , but the lack of an external power supply justifies the small increase in size ." +"I had to buy a wireless mouse to go with it , as I am old school and hate the pad , but knew that before I bought it , now it works great , need to get adjusted to the key board , as I am used to a bigger one and pounding ." +"Has all the other features I wanted including a VGA port , HDMI , ethernet and 3 USB ports ." +The only thing I dislike about this laptop are the rubber pads found on the bottom of the computer for grip . +It 's a decent computer for the price and hopefully it will last a long time . +The nicest part is the low heat output and ultra quiet operation . +"this Mac Mini does not have a built-in mic , and it would seem that its Mac OS 10.9 does not handle external microphones properly ." +A lot of features and shortcuts on the MBP that I was never exposed to on a normal PC . +Was n't sure if I was going to like it much less love it so I went to a local best buy and played around with the IOS system on a Mac Pro and it was totally unique and different . +air has higher resolution but the fonts are small . +"working with Mac is so much easier , so many cool features ." +I like the brightness and adjustments . +I only wish this mac had a CD/DVD player built in . +The only thing I miss is that my old Alienware laptop had backlit keys . +"So happy with this purchase , I just wish it came with Microsoft Word ." +It has enough memory and speed to run my business with all the flexibility that comes with a laptop . +"The battery life is excellent , the display is excellent , and downloading apps is a breeze ." +"The screen , the software and the smoothness of the operating system ." +"But with this laptop , the bass is very weak and the sound comes out sounding tinny ." +"The built quality is really good , I was so Happy and excited about this Product ." +I am loving the fast performance also . +"Further , this Mac Mini has a sloppy Bluetooth interface ( courtesy of the Mac OS ) and the range is poor ." +My only gripe would be the need to add more RAM . +Fine if you have a touch screen . +"This by far beats any computer out on the market today built well , battery life AMAZING ." +"The OS is easy , and offers all kinds of surprises ." +A veryimportant feature is Firewire 800 which in my experience works better then USB3 ( in PC enabled with USB3 ) I was not originally sold on the MAC OS I felt it was inferior in many ways To Windows 7 . +"I like iTunes , the apparent security , the Mini form factor , all the nice graphics stuff ." +"After replacing the spinning hard disk with an ssd drive , my mac is just flying ." +I know some people complained about HDMI issues but they released a firmware patch to address that issue . +With the needs of a professional photographer I generally need to keep up with the best specs . +packing and everything was perfect +I called Toshiba where I gave them the serial number and they informed me that they were having issues with the mother boards . +"I seem to be having repeat problems as the Mother Board in this one is diagnosed as faulty , related to the graphics card ." +It also comes with 4G of RAM but if you 're like me you want to max that out so I immediately put 8G of RAM in her and I 've never used a computer that performs better . +This computer is also awesome for my sons virtual home schooling . +Cost is more as compared to other brands . +also ... - excellent operating system -- size and weight for optimal mobility -- excellent durability of the battery -- the functions provided by the trackpad is unmatched by any other brand- +This hardware seems to be better than the iMac in that it is n't $ 1400 and smaller . +I 've had it for about 2 months now and found no issues with software or updates . +the latest version does not have a disc drive . +Screen - although some people might complain about low res which I think is ridiculous . diff --git a/format_output.py b/format_output.py new file mode 100644 index 0000000..3c48f10 --- /dev/null +++ b/format_output.py @@ -0,0 +1,77 @@ +import argparse + +parser = argparse.ArgumentParser(description="Predict using the model.") +parser.add_argument('--dataset', type=str, required=True, help='Dataset name') +parser.add_argument('--random_seed', type=int, required=True, help='Random seed') +args = parser.parse_args() +dataset = args.dataset +seed = args.random_seed + +with open(f'pred/{dataset}/{dataset}_pred_seed{seed}.csv', 'r', encoding='utf-8') as file: + # 所有语句的内容 + newlines = [] + # 所有标签的内容 + all_tags = [] + for line in file: + # 找到分析结果开始的位置 + start_index = line.find('#### #### ####') + if start_index != -1: + analysis_result = line[start_index + len('#### #### ####'):].strip() + parsed_result = eval(analysis_result) + assert isinstance(parsed_result, list) + # 每一行的标签 + pairs = [] + if not parsed_result: + pairs.append([]) + for aos in parsed_result: + a = aos[0] + o = aos[1] + s = aos[2] + words = line.split() + aspect = [] + opinion = [] + if len(a) == 2: + aspect = words[a[0]: a[1]+1] + else: + aspect = words[a[0]] + if len(o) == 2: + opinion = words[o[0]: o[1]+1] + else: + opinion = words[o[0]] + pair = [aspect, opinion, s] + pairs.append(pair) + + newline = line.split(' .#### #### ####')[0].strip() + for pair in pairs: + for i, item in enumerate(pair): + if isinstance(item, list): + pair[i] = ' '.join(item) + all_tags.append(pairs) + newlines.append(newline) + +import csv + +save_path = f'pred/{dataset}/{dataset}_pred_seed{seed}_formatted.csv' + +# 将 newlines 和 all_tags 写入到 CSV 文件中 +with open(save_path, 'w', newline='', encoding='utf-8') as csvfile: + writer = csv.writer(csvfile) + + headers = ['Sentences'] + ['[Aspect, Opinion, Sentiment]'] + writer.writerow(headers) + + for i in range(max(len(newlines), len(all_tags))): + row = [] + if i < len(newlines): + row.append(newlines[i]) + else: + row.append('') + + if i < len(all_tags): + row.extend(all_tags[i]) + else: + row.extend([''] * len(all_tags)) + + writer.writerow(row) + +print(f'结果保存成功。') diff --git a/main.py b/main.py new file mode 100644 index 0000000..350b25f --- /dev/null +++ b/main.py @@ -0,0 +1,60 @@ +""" + 这是入口脚本。 + + 数据格式: + 参考dataset中的示例数据集。 + + 参数说明: + dataset:放在dataset目录下的待预测的csv文件名称。 + using_train: 是否要重新训练数据,还是直接使用pretrain_weight中的权重 + model_name:采用这个数据集进行训练,日志和权重保存在outputs/{model_name}目录中。 + random_seed:采用这个种子进行训练。 + + 结果保存: + 在pred目录下对应数据集的文件夹中。 + +""" + +import argparse +import subprocess +import os + +dataset = "14lap" +using_train = True +model_name = "14lap" # 可选值有"14lap" "14res" "15res" "16res" +random_seed = 18 + + +def main(): + parser = argparse.ArgumentParser(description="Main script for running the project.") + + parser.add_argument('--dataset', type=str, default=dataset, help='Dataset name') + parser.add_argument('--model_name', type=str, default=model_name, help='Model name') + parser.add_argument('--random_seed', type=int, default=random_seed, help='Random seed') + parser.add_argument('--using_train', type=bool, default=using_train, help='Using train') + args = parser.parse_args() + + # 训练模型,得到的权重保存在outputs中 + if not os.path.exists(f'outputs/{dataset}/seed{random_seed}') and using_train: + print("Training...") + subprocess.run(['python', 'train.py', + '--random_seed', str(args.random_seed), + '--model_name', args.model_name]) + + # 使用outputs中对应种子和名称的模型,执行预测 + print("Predicting...") + using_train_str = "" if not using_train else "True" + subprocess.run(['python', 'pred.py', + '--dataset', args.dataset, + '--model_name', args.model_name, + '--random_seed', str(args.random_seed), + '--using_train', using_train_str]) + + # 处理数据格式,保存到pred文件夹中 + subprocess.run(['python', 'format_output.py', + '--dataset', args.dataset, + '--random_seed', str(args.random_seed)]) + + +if __name__ == "__main__": + main() diff --git a/pred.py b/pred.py new file mode 100644 index 0000000..52c059f --- /dev/null +++ b/pred.py @@ -0,0 +1,51 @@ +import argparse +import pandas as pd + +# 加载参数 +parser = argparse.ArgumentParser(description="Predict using the model.") +parser.add_argument('--dataset', type=str, required=True, help='Dataset name') +parser.add_argument('--model_name', type=str, required=True, help='Model name') +parser.add_argument('--random_seed', type=int, required=True, help='Random seed') +parser.add_argument('--using_train', type=bool, required=True, help='Using train') + +args = parser.parse_args() +dataset = args.dataset +model_name = args.model_name +random_seed = args.random_seed +using_train = args.using_train + +# 在数据后添加标签使其符合格式要求,并保存到aste/temp_data中 +df = pd.read_csv("dataset/"+dataset+".csv", header=None) + +selected_sentences = [] +selected_sentences = df.iloc[:, 0].tolist() + +tag = " .#### #### ####[]\n" +tagged_sentences = [f"{sentence}{tag}" for sentence in selected_sentences] + +import re +for line in tagged_sentences: + # 检查分隔符 + if not re.search(r"#### ####", line): + print(line) + +with open('aste/temp_data/'+dataset+'.csv', 'w', encoding='utf-8') as file: + file.writelines(tagged_sentences) + +################################################### + +# 使用训练好的模型进行预测,结果保存到目录pred中 +from aste.wrapper import SpanModel + +save_dir = "pred" + +if using_train: + model_dir = f"outputs/{model_name}/seed_{random_seed}" +else: + model_dir = f"pretrained_weight/{model_name}" + +model = SpanModel(save_dir=model_dir, random_seed=random_seed) +output_dir = f"{save_dir}/{dataset}/{dataset}_pred_seed{random_seed}.csv" +test_data_path = f"aste/temp_data/{dataset}.csv" + +model.predict(path_in=test_data_path, path_out=output_dir) diff --git a/pred/14lap/14lap_pred_seed18.csv b/pred/14lap/14lap_pred_seed18.csv new file mode 100644 index 0000000..84b0719 --- /dev/null +++ b/pred/14lap/14lap_pred_seed18.csv @@ -0,0 +1,328 @@ +Boot time is super fast , around anywhere from 35 seconds to 1 minute . .#### #### ####[([0, 1], [4], 'POS')] +tech support would not fix the problem unless I bought your plan for $ 150 plus . .#### #### ####[] +Set up was easy . .#### #### ####[([0, 1], [3], 'POS')] +Did not enjoy the new Windows 8 and touchscreen functions . .#### #### ####[([5, 6], [0, 2], 'NEG'), ([5, 6], [4], 'NEU')] +Other than not being a fan of click pads ( industry standard these days ) and the lousy internal speakers , it 's hard for me to find things about this notebook I do n't like , especially considering the $ 350 price tag . .#### #### ####[([18, 19], [17], 'NEG')] +It 's fast , light , and simple to use . .#### #### ####[([9], [2], 'POS'), ([9], [4], 'POS'), ([9], [7], 'POS')] +Works well , and I am extremely happy to be back to an apple OS . .#### #### ####[([0], [1], 'POS'), ([13, 14], [7], 'NEU')] +Sure it 's not light and slim but the features make up for it 100 % . .#### #### ####[([9], [10, 11], 'POS')] +I am pleased with the fast log on , speedy WiFi connection and the long battery life ( > 6 hrs ) . .#### #### ####[([6], [5], 'POS'), ([10, 11], [9], 'POS'), ([15, 16], [14], 'POS')] +The Apple engineers have not yet discovered the delete key . .#### #### ####[] +Made interneting ( part of my business ) very difficult to maintain . .#### #### ####[] +Luckily , for all of us contemplating the decision , the Mac Mini is priced just right . .#### #### ####[([14], [16], 'POS')] +Only problem that I had was that the track pad was not very good for me , I only had a problem once or twice with it , But probably my computer was a bit defective . .#### #### ####[([8, 9], [1], 'NEG'), ([8, 9], [11, 13], 'NEG')] +It is super fast and has outstanding graphics . .#### #### ####[([7], [6], 'POS')] +But the mountain lion is just too slow . .#### #### ####[([2, 3], [7], 'NEG')] +Strong build though which really adds to its durability . .#### #### ####[([1], [0], 'POS'), ([1], [5], 'POS'), ([8], [5], 'POS')] +The battery life is excellent -- 6-7 hours without charging . .#### #### ####[([1, 2], [4], 'POS')] +I 've had my computer for 2 weeks already and it works perfectly . .#### #### ####[([11], [12], 'POS')] +And I may be the only one but I am really liking Windows 8 . .#### #### ####[([12, 13], [11], 'POS')] +The baterry is very longer . .#### #### ####[([1], [4], 'NEG')] +Its size is ideal and the weight is acceptable . .#### #### ####[([1], [3], 'POS'), ([6], [8], 'POS')] +I can say that I am fully satisfied with the performance that the computer has supplied . .#### #### ####[([10], [7], 'POS')] +It has so much more speed and the screen is very sharp . .#### #### ####[([5], [4], 'POS'), ([8], [11], 'NEG')] +Everything I wanted and everything I needed and the price was great ! .#### #### ####[([9], [11], 'POS')] +It 's not inexpensive but the Hardware performance is impressive for a computer this small . .#### #### ####[([6, 7], [9], 'POS')] +This thing is awesome , everything always works , everything is always easy to set up , everything is compatible , its literally everything I could ask for . .#### #### ####[([14, 15], [12], 'POS'), ([14, 15], [19], 'POS')] +Keyboard responds well to presses . .#### #### ####[([0], [2], 'POS')] +Lastly , Windows 8 is annoying . .#### #### ####[([2, 3], [5], 'NEG')] +Everything is so easy and intuitive to setup or configure . .#### #### ####[([7], [3], 'POS'), ([9], [3], 'POS'), ([7], [5], 'POS'), ([9], [5], 'POS')] +Biggest complaint is Windows 8 . .#### #### ####[([3, 4], [1], 'NEG')] +Only 2 usb ports ... seems kind of ... limited . .#### #### ####[([2, 3], [9], 'NEG')] +It has all the expected features and more +plus a wide screen and more than roomy keyboard . .#### #### ####[([5], [4], 'POS'), ([11], [10], 'POS')] +Amazing Performance for anything I throw at it . .#### #### ####[([1], [0], 'POS')] +The receiver was full of superlatives for the quality and performance . .#### #### ####[([1], [5], 'POS'), ([8], [5], 'POS'), ([10], [5], 'POS')] +I was extremely happy with the OS itself . .#### #### ####[([6], [3], 'POS')] +The new MBP offers great portability and gives us confidence that we are not going to need to purchase a new laptop in 18 months . .#### #### ####[([5], [4], 'POS')] +The criticism has waned , and now I 'd be the first to recommend an Air for truly portable computing . .#### #### ####[([1], [3], 'NEG')] +MS Office 2011 for Mac is wonderful , well worth it . .#### #### ####[] +But the performance of Mac Mini is a huge disappointment . .#### #### ####[([2], [9], 'NEG')] +They do n't just look good ; they deliver excellent performance . .#### #### ####[([10], [9], 'POS')] +I have had it over a year now with out a Glitch of any kind..I love the lit up keys and screen display ... this thing is Fast and clear as can be . .#### #### ####[([17, 19], [15], 'POS'), ([21, 22], [15], 'POS'), ([21, 22], [27], 'POS'), ([21, 22], [29], 'POS')] +The Mountain Lion OS is not hard to figure out if you are familiar with Microsoft Windows . .#### #### ####[([1, 3], [5, 6], 'POS')] +However , I can refute that OSX is `` FAST '' . .#### #### ####[([6], [9], 'POS')] +Enjoy using Microsoft Office ! .#### #### ####[] +Incredible graphics and brilliant colors . .#### #### ####[([1], [0], 'POS'), ([4], [3], 'POS')] +Built-in apps are purely amazing . .#### #### ####[([0, 1], [4], 'POS')] +From the speed to the multi touch gestures this operating system beats Windows easily . .#### #### ####[([2], [13], 'POS'), ([9, 10], [13], 'POS')] +I really like the size and I 'm a fan of the ACERS . .#### #### ####[([4], [2], 'POS')] +I opted for the SquareTrade 3-Year Computer Accidental Protection Warranty ( $ 1500-2000 ) which also support `` accidents '' like drops and spills that are NOT covered by AppleCare . .#### #### ####[([29], [26, 27], 'NEU')] +It 's light and easy to transport . .#### #### ####[([6], [4], 'POS')] +Once you get past learning how to use the poorly designed Windows 8 Set-Up you may feel frustrated . .#### #### ####[] +The aluminum body sure makes it stand out . .#### #### ####[([1, 2], [6, 7], 'POS')] +It is very easy to integrate bluetooth devices , and USB devices are recognized almost instantly . .#### #### ####[([6, 7], [3], 'NEU'), ([10, 11], [3], 'NEU')] +And the fact that Apple is driving the 13 '' RMBP with the Intel4000 graphic chip seems underpowered ( to me . .#### #### ####[] +Apple removed the DVD drive Firewire port ( will work with adapter ) and put the SDXC slot in a silly position on the back . .#### #### ####[([3, 6], [1], 'NEU'), ([16, 17], [20], 'NEU')] +The durability of the laptop will make it worth the money . .#### #### ####[([1], [8], 'POS')] +Well designed and fast . .#### #### ####[] +But I was completely wrong , this computer is UNBELIEVABLE amazing and easy to use . .#### #### ####[([14], [10], 'POS'), ([14], [12], 'POS')] +Exactly as posted plus a great value . .#### #### ####[([6], [5], 'POS')] +The specs are pretty good too . .#### #### ####[([1], [4], 'POS')] +Apple is unmatched in product quality , aesthetics , craftmanship , and customer service . .#### #### ####[([7], [2], 'POS'), ([9], [2], 'POS'), ([12, 13], [2], 'POS')] +It is a great size and amazing windows 8 included ! .#### #### ####[([4], [3], 'POS'), ([7, 8], [6], 'POS')] +I do not like too much Windows 8 . .#### #### ####[([6, 7], [2, 3], 'NEG')] +Startup times are incredibly long : over two minutes . .#### #### ####[([0, 1], [4], 'NEG')] +Also stunning colors and speedy .#### #### ####[([2], [1], 'POS'), ([2], [4], 'POS')] +great price free shipping what else can i ask for ! ! .#### #### ####[([1], [0], 'POS'), ([3], [0], 'POS'), ([1], [2], 'POS'), ([3], [2], 'POS')] +This mouse is terrific . .#### #### ####[([1], [3], 'POS')] +It is really thick around the battery . .#### #### ####[([6], [3], 'NEG')] +And windows 7 works like a charm . .#### #### ####[([1, 2], [6], 'POS')] +: ) Great product , great price , great delivery , and great service . .#### #### ####[([6], [5], 'POS'), ([9], [8], 'POS'), ([13], [12], 'POS')] +: ] It arrived so fast and customer service was great . .#### #### ####[([7, 8], [10], 'POS')] +tried windows 8 and hated it ! ! ! .#### #### ####[([1, 2], [4], 'NEG')] +Set up was a breeze . .#### #### ####[([0, 1], [4], 'POS')] +But I do NOT like Win8 . .#### #### ####[([5], [3, 4], 'NEG')] +I had the same reasons as most PC users : the price , the overbearing restrictions of OSX and lack of support for games . .#### #### ####[([17], [19], 'NEG'), ([21], [19], 'NEG'), ([23], [19], 'NEG')] +I wanted it for it 's mobility and man , this little bad boy is very nice . .#### #### ####[([6], [16], 'POS')] +I found the mini to be : Exceptionally easy to set up .#### #### ####[([10, 11], [8], 'POS')] +The sound is nice and loud ; I do n't have any problems with hearing anything . .#### #### ####[([1], [3], 'POS'), ([1], [5], 'POS'), ([1], [8, 12], 'POS')] +It is very slim , the track pad is very much impressed with me . .#### #### ####[([6, 7], [11], 'POS')] +The settings are not user-friendly either . .#### #### ####[([1], [3, 4], 'NEG')] +Thank goodness for OpenOffice ! .#### #### ####[] +Awesome form factor , great battery life , wonderful UX . .#### #### ####[([1, 2], [0], 'POS'), ([5, 6], [4], 'POS'), ([9], [8], 'POS')] +i love the keyboard and the screen . .#### #### ####[([3], [1], 'POS'), ([6], [1], 'POS')] +However , there are MAJOR issues with the touchpad which render the device nearly useless . .#### #### ####[([8], [5], 'NEG'), ([8], [14], 'NEG'), ([12], [14], 'NEG')] +I 've already upgraded o Mavericks and I am impressed with everything about this computer . .#### #### ####[] +Not as fast as I would have expect for an i5 . .#### #### ####[] +thanks for great service and shipping ! .#### #### ####[([3], [0], 'POS'), ([3], [2], 'POS'), ([5], [2], 'POS')] +The performance seems quite good , and built-in applications like iPhoto work great with my phone and camera . .#### #### ####[([1], [4], 'POS'), ([7, 8], [12], 'POS'), ([10], [12], 'POS')] +I did swap out the hard drive for a Samsung 830 SSD which I highly recommend . .#### #### ####[([5, 6], [2, 3], 'NEU'), ([5, 6], [15], 'NEU')] +Yes , that 's a good thing , but it 's made from aluminum that scratches easily . .#### #### ####[([13], [16], 'POS'), ([15], [16], 'POS')] +I was also informed that the components of the Mac Book were dirty . .#### #### ####[([6], [12], 'NEG')] +the hardware problems have been so bad , i ca n't wait till it completely dies in 3 years , TOPS ! .#### #### ####[([1], [2], 'NEG'), ([1], [6], 'NEG')] +It 's so nice that the battery last so long and that this machine has the snow lion ! .#### #### ####[([6], [3], 'POS'), ([6], [9], 'POS')] +it 's exactly what i wanted , and it has all the new features and whatnot . .#### #### ####[([13], [12], 'POS')] +It feels cheap , the keyboard is not very sensitive . .#### #### ####[([5], [7, 9], 'NEG')] +Though please note that sometimes it crashes , and the sound quality isnt superb . .#### #### ####[([10, 11], [12, 13], 'NEG')] +It is very easy to navigate even for a novice . .#### #### ####[([5], [3], 'POS')] +Does everything I need it to , has a wonderful battery life and I could n't be happier . .#### #### ####[([10, 11], [9], 'POS')] +Great Performance and Quality . .#### #### ####[([1], [0], 'POS'), ([3], [0], 'POS')] +One more thing , this mac does NOT come with restore disks and I am not sure if you can make them direct from the mac like you can with newer PC 's , also the charging cables are made of the same cheap material as the iPhone/iPod touch cables . .#### #### ####[] +The new os is great on my macbook pro ! .#### #### ####[([2], [1], 'POS'), ([2], [4], 'POS')] +I have experienced no problems , works as anticipated . .#### #### ####[([6], [3, 4], 'POS')] +System is running great . .#### #### ####[([0], [3], 'POS')] +Easy to customize setting and even create your own bookmarks . .#### #### ####[([3], [0], 'POS')] +it has all the features that we expected and the price was good , working well so far . .#### #### ####[([10], [12], 'POS')] +The new operating system makes this computer into a super iPad . .#### #### ####[([2, 3], [1], 'POS')] +Easy to set up and go ! .#### #### ####[([2, 3], [0], 'POS')] +I ca n't believe how quiet the hard drive is and how quick this thing boots up . .#### #### ####[([7, 8], [5], 'NEG'), ([7, 8], [12], 'POS')] +It 's just what we were looking for and it works great . .#### #### ####[([10], [11], 'POS')] +It 's so quick and responsive that it makes working / surfing on a computer so much more pleasurable ! .#### #### ####[([11], [18], 'POS')] +It works fine , and all the software seems to run pretty well . .#### #### ####[([1], [2], 'POS'), ([7], [12], 'POS')] +I wanted a computer that was quite , fast , and that had overall great performance . .#### #### ####[([15], [14], 'POS')] +Harddrive was in poor condition , had to replace it . .#### #### ####[([0], [3], 'NEG')] +The on/off switch is a bit obscure in the rear corner . .#### #### ####[([1, 2], [6], 'NEG')] +My only complaint is the total lack of instructions that come with the mac mini . .#### #### ####[([8], [2], 'NEG'), ([8], [6], 'NEG')] +The only task that this computer would not be good enough for would be gaming , otherwise the integrated Intel 4000 graphics work well for other tasks . .#### #### ####[([19, 21], [18], 'NEU'), ([19, 21], [23], 'NEU')] +I use it mostly for content creation ( Audio , video , photo editing ) and its reliable . .#### #### ####[([5, 6], [3], 'POS'), ([5, 6], [17], 'POS'), ([12, 13], [17], 'POS')] +Screen is bright and gorgeous . .#### #### ####[([0], [2], 'POS'), ([0], [4], 'POS')] +It is robust , with a friendly use as all Apple products . .#### #### ####[([7], [6], 'POS')] +It is fast and easy to use . .#### #### ####[([6], [2], 'POS'), ([6], [4], 'POS')] +And the fact that it comes with an i5 processor definitely speeds things up .#### #### ####[([8, 9], [11, 13], 'POS')] +I have been PC for years but this computer is intuitive and its built in features are a great help .#### #### ####[([13, 15], [18, 19], 'POS')] +Nice screen , keyboard works great ! .#### #### ####[([1], [0], 'POS'), ([3], [0], 'POS'), ([3], [5], 'POS')] +I was amazed at how fast the delivery was . .#### #### ####[([7], [2], 'POS'), ([7], [5], 'POS')] +The memory was gone and it was not able to be used . .#### #### ####[([1], [3], 'NEG')] +It works great and I am so happy I bought it . .#### #### ####[([1], [2], 'POS')] +I like the design and ease of use with the keyboard , plenty of ports . .#### #### ####[([3], [1], 'POS'), ([10], [1], 'POS'), ([10], [12], 'POS'), ([14], [12], 'POS')] +it definitely beats my old mac and the service was great . .#### #### ####[([8], [10], 'POS')] +Web browsing is very quick with Safari browser . .#### #### ####[([0, 1], [4], 'POS'), ([6, 7], [4], 'POS')] +I like the lighted screen at night . .#### #### ####[([3, 4], [1], 'POS')] +It is really easy to use and it is quick to start up . .#### #### ####[([5], [3], 'POS'), ([11, 12], [9], 'POS')] +I 've lived with the crashes and slow operation and restarts . .#### #### ####[([8], [7], 'NEG')] +USB3 Peripherals are noticably less expensive than the ThunderBolt ones . .#### #### ####[([0, 1], [5], 'NEG')] +It 's fast , light , and is perfect for media editing , which is mostly why I bought it in the first place . .#### #### ####[([10, 11], [8], 'POS')] +The battery lasts as advertised ( give or take 15-20 minutes ) , and the entire user experience is very elegant . .#### #### ####[([16, 17], [20], 'POS')] +Thanks for the fast shipment and great price . .#### #### ####[([4], [0], 'POS'), ([4], [3], 'POS'), ([7], [6], 'POS')] +! Excellent performance , usability , presentation and time response . .#### #### ####[([2], [1], 'POS'), ([4], [1], 'POS'), ([6], [1], 'POS'), ([8, 9], [1], 'POS')] +The smaller size was a bonus because of space restrictions . .#### #### ####[([2], [1], 'NEG')] +I blame the Mac OS . .#### #### ####[([3, 4], [1], 'NEG')] +I like the operating system . .#### #### ####[([3, 4], [1], 'POS')] +I love the form factor . .#### #### ####[([3, 4], [1], 'POS')] +It 's fast at loading the internet . .#### #### ####[([6], [2], 'NEU')] +So much faster and sleeker looking . .#### #### ####[] +Unfortunately , it runs XP and Microsoft is dropping support next April . .#### #### ####[([9], [8], 'NEG')] +First off , I really do like my MBP ... once used to the OS it is pretty easy to get around , and the overall build is great ... eg the keyboard is one of the best to type on . .#### #### ####[([14], [18], 'POS'), ([26], [28], 'POS'), ([32], [28], 'POS'), ([32], [37], 'POS')] +It is made of such solid construction and since I have never had a Mac using my iPhone helped me get used to the system a bit . .#### #### ####[([6], [5], 'POS')] +Very nice unibody construction . .#### #### ####[([2, 3], [1], 'POS')] +This Macbook Pro is fast , powerful , and runs super quiet and cool . .#### #### ####[([9], [11], 'POS'), ([9], [13], 'POS')] +It 's ok but does n't have a disk drive which I did n't know until after I bought it . .#### #### ####[([8, 9], [4, 6], 'NEG')] +There is no HDMI receptacle , nor is there an SD card slot located anywhere on the device . .#### #### ####[([3, 4], [2], 'NEG')] +It came in brand new and works perfectly . .#### #### ####[([6], [7], 'POS')] +It should n't happen like that , I do n't have any design app open or anything . .#### #### ####[] +MY TRACKPAD IS NOT WORKING . .#### #### ####[([1], [3, 4], 'NEG')] +It looks and feels solid , with a flawless finish . .#### #### ####[([9], [8], 'POS')] +Price was higher when purchased on MAC when compared to price showing on PC when I bought this product . .#### #### ####[([0], [2], 'NEG')] +Then the system would many times not power down without a forced power-off . .#### #### ####[([2], [6], 'NEG')] +The configuration is perfect for my needs . .#### #### ####[([1], [3], 'POS')] +and the speakers is the worst ever . .#### #### ####[([2], [5], 'NEG')] +Its the best , its got the looks , super easy to use and love all you can do with the trackpad ! .. .#### #### ####[([12], [10], 'POS')] +Web surfuring is smooth and seamless . .#### #### ####[([0, 1], [3], 'POS'), ([0, 1], [5], 'POS')] +I 'm overall pleased with the interface and the portability of this product . .#### #### ####[([6], [3], 'POS'), ([9], [3], 'POS')] +This item is a beautiful piece , it works well , it is easy to carry and handle . .#### #### ####[([8], [9], 'POS'), ([15], [13], 'POS'), ([17], [13], 'POS')] +It was also suffering from hardware ( keyboard ) issues , relatively slow performance and shortening battery lifetime . .#### #### ####[([5], [3], 'NEG'), ([7], [9], 'NEG'), ([13], [12], 'NEG'), ([16, 17], [15], 'NEG')] +Runs good and does the job , ca n't complain about that ! .#### #### ####[([0], [1], 'POS')] +It 's silent and has a very small footprint on my desk . .#### #### ####[([8], [7], 'NEG')] +The exterior is absolutely gorgeous . .#### #### ####[([1], [4], 'POS')] +It has a very high performance , just for what I needed for . .#### #### ####[([5], [4], 'POS')] +Apple is aware of this issue and this is either old stock or a defective design involving the intel 4000 graphics chipset . .#### #### ####[([15], [14], 'NEG')] +I just bought the new MacBook Pro , the 13 '' model , and I ca n't believe Apple keeps making the same mistake with regard to USB ports . .#### #### ####[([27, 28], [23], 'NEU')] +It is the perfect size and speed for me . .#### #### ####[([4], [3], 'POS'), ([6], [3], 'POS')] +THE CUSTOMER SERVICE IS TERRIFIC ! ! .#### #### ####[([1, 2], [4], 'POS')] +My last laptop was a 17 '' ASUS gaming machine , which performed admirably , but having since built my own desktop and really settling into the college life , I found myself wanting something smaller and less cumbersome , not to mention that the ASUS had been slowly developing problems ever since I bought it about 4 years ago . .#### #### ####[([12], [13], 'POS')] +However , it did not have any scratches , ZERO battery cycle count ( pretty surprised ) , and all the hardware seemed to be working perfectly . .#### #### ####[([10, 12], [9], 'NEG'), ([21], [26], 'POS')] +And as for all the fancy finger swipes -- I just gave up and attached a mouse . .#### #### ####[([6, 7], [5], 'NEG')] +I needed a laptop with big storage , a nice screen and fast so I can photoshop without any problem . .#### #### ####[([6], [5], 'POS'), ([10], [9], 'POS'), ([10], [12], 'POS')] +I like coming back to Mac OS but this laptop is lacking in speaker quality compared to my $ 400 old HP laptop . .#### #### ####[([13, 14], [11], 'NEG')] +Shipped very quickly and safely . .#### #### ####[([0], [2], 'POS'), ([0], [4], 'POS')] +The thunderbolt port is awesome ! .#### #### ####[([1, 2], [4], 'POS')] +The performance is definitely superior to any computer I 've ever put my hands on . .#### #### ####[([1], [4], 'POS')] +It 's great for streaming video and other entertainment uses . .#### #### ####[([4, 5], [2], 'POS'), ([8, 9], [2], 'POS')] +I like the design and its features but there are somethings I think needs to be improved . .#### #### ####[([3], [1], 'POS'), ([6], [1], 'POS')] +There were small problems with Mac office . .#### #### ####[([5, 6], [3], 'NEG')] +I ordered my 2012 mac mini after being disappointed with spec of the new 27 '' Imacs . .#### #### ####[([10], [8], 'NEG')] +Its fast , easy to use and it looks great . .#### #### ####[([5], [1], 'POS'), ([5], [3], 'POS')] +Performance is much much better on the Pro , especially if you install an SSD on it . .#### #### ####[([0], [4], 'POS')] +Note , however , that any existing MagSafe accessories you have will not work with the MagSafe 2 connection . .#### #### ####[([7, 8], [12, 13], 'NEG'), ([7, 8], [12, 14], 'NEG')] +The only thing I dislike is the touchpad , alot of the times its unresponsive and does things I dont want it too , I would recommend using a mouse with it . .#### #### ####[([7], [4], 'NEG')] +The Mac mini is about 8x smaller than my old computer which is a huge bonus and runs very quiet , actually the fans are n't audible unlike my old pc .#### #### ####[([23], [24, 26], 'NEG')] +I thought the transition would be difficult at best and would take some time to fully familiarize myself with the new Mac ecosystem . .#### #### ####[([21, 22], [6], 'NEG')] +It 's absolutely wonderful and worth the price ! .#### #### ####[([7], [5], 'POS')] +I am please with the products ease of use ; out of the box ready ; appearance and functionality . .#### #### ####[([8], [2], 'POS'), ([8], [6], 'POS')] +Perfect for all my graphic design classes I 'm taking this year in college : - ) .#### #### ####[] +I will not be using that slot again . .#### #### ####[] +The OS is fast and fluid , everything is organized and it 's just beautiful . .#### #### ####[([1], [3], 'POS'), ([1], [5], 'POS'), ([1], [14], 'POS')] +They are simpler to use . .#### #### ####[([4], [2], 'POS')] +! so nice .. stable .. fast .. now i got my SSD ! .#### #### ####[([12], [6], 'NEU')] +I love the quick start up . .#### #### ####[([4, 5], [1], 'POS'), ([4, 5], [3], 'POS')] +You just can not beat the functionality of an Apple device . .#### #### ####[([6], [2, 4], 'NEG')] +Yet my mac continues to function properly . .#### #### ####[([5], [6], 'POS')] +Graphics are much improved . .#### #### ####[([0], [3], 'POS')] +Here are the things that made me confident with my purchase : Build Quality - Seriously , you ca n't beat a unibody construction . .#### #### ####[([12, 13], [7], 'POS'), ([22, 23], [7], 'NEU'), ([22, 23], [18, 20], 'NEG')] +It provides much more flexibility for connectivity . .#### #### ####[([6], [4], 'POS')] +Mac tutorials do help . .#### #### ####[([0, 1], [3], 'NEU')] +The technical support was not helpful as well . .#### #### ####[([1, 2], [4, 5], 'NEG'), ([1, 2], [4, 7], 'NEG')] +I got the new adapter and there was no change . .#### #### ####[([4], [3], 'NEU')] +Logic board utterly fried , cried , and laid down and died . .#### #### ####[([0, 1], [3], 'NEG')] +The sound was crappy even when you turn up the volume still the same results . .#### #### ####[([1], [3], 'NEG')] +OSX Lion is a great performer..extremely fast and reliable . .#### #### ####[] +Having heard from friends and family about how reliable a Mac product is , I never expected to have an application crash within the first month , but I did . .#### #### ####[([20], [21], 'NEG')] +The Macbook pro 's physical form is wonderful . .#### #### ####[([4, 5], [7], 'POS')] +The Mini 's body has n't changed since late 2010- and for a good reason . .#### #### ####[] +The unibody construction really does feel lot more solid than Apple 's previous laptops . .#### #### ####[([1, 2], [8], 'POS')] +3D rendering slows it down considerably . .#### #### ####[] +fast , great screen , beautiful apps for a laptop ; priced at 1100 on the apple website ; amazon had it for 1098+ tax - plus i had a 10 % off coupon from amazon-cost me 998 plus tax- 1070- OTD ! .#### #### ####[([3], [0], 'POS'), ([3], [2], 'POS'), ([6], [5], 'POS')] +All the ports are much needed since this is my main computer . .#### #### ####[] +The Like New condition of the iMac MC309LL/A on Amazon is at $ 900+ level only , and it is a Quad-Core 2.5 GHz CPU ( similar to the $ 799 Mini ) , with Radeon HD 6750M 512MB graphic card ( this mini is integrated Intel 4000 card ) , and it even comes with wireless Apple Keyboard and Mouse , all put together in neat and nice package . .#### #### ####[([69], [68], 'POS')] +Put a cover on it and is a little better but that is my only complaint . .#### #### ####[] +Within a few hours I was using the gestures unconsciously . .#### #### ####[([8], [9], 'NEU')] +This mac does come with an extender cable and I 'm using mine right now hoping the cable will stay nice for the many years I plan on using this mac . .#### #### ####[([6, 7], [20], 'NEU'), ([17], [20], 'POS')] +The 2.9ghz dual-core i7 chip really out does itself . .#### #### ####[] +It is pretty snappy and starts up in about 30 seconds which is good enough for me . .#### #### ####[] +Not sure on Windows 8 . .#### #### ####[([3, 4], [0, 1], 'NEG')] +My one complaint is that there was no internal CD drive . .#### #### ####[([8, 10], [2], 'NEG'), ([8, 10], [7], 'NEG')] +This newer netbook has no hard drive or network lights . .#### #### ####[([5, 6], [4], 'NEG')] +Not too expense and has enough storage for most users and many ports . .#### #### ####[([6], [5], 'POS')] +The audio volume is quite low and virtually unusable in a room with any background activity . .#### #### ####[([1, 2], [5], 'NEG'), ([1, 2], [8], 'NEG')] +It is lightweight and the perfect size to carry to class . .#### #### ####[([6], [5], 'POS')] +The MBP is beautiful has many wonderful capabilities . .#### #### ####[([1], [3], 'POS'), ([7], [6], 'POS')] +I thought that it will be fine , if i do some settings . .#### #### ####[([12], [6], 'NEU')] +Runs very smoothly . .#### #### ####[([0], [2], 'POS')] +Boot-up slowed significantly after all Windows updates were installed . .#### #### ####[([0], [1], 'NEG')] +It was important that it was powerful enough to do all of the tasks he needed on the internet , word processing , graphic design and gaming . .#### #### ####[([20, 21], [6], 'POS'), ([23, 24], [6], 'POS')] +I like the Mini Mac it was easy to setup and install , but I am learning as I go and could use a tutorial to learn how to use some of the features I was use to on the PC especially the right mouse click menu . .#### #### ####[([9], [7], 'POS')] +Runs real quick . .#### #### ####[([0], [2], 'POS')] +Since the machine 's slim profile is critical to me , that was a problem . .#### #### ####[([5], [4], 'NEG'), ([5], [7], 'NEG')] +WiFi capability , disk drive and multiple USB ports to connect scale and printers was all that was required . .#### #### ####[] +The SD card reader is slightly recessed and upside down ( the nail slot on the card can not be accessed ) , if this was a self ejecting slot this would not be an issue , but its not . .#### #### ####[([1, 3], [6], 'NEG'), ([12, 13], [6], 'NEU'), ([12, 13], [8, 9], 'NEU'), ([12, 13], [17, 20], 'NEG')] +Soft touch , anodized aluminum with laser cut precision and no flaws . .#### #### ####[([1], [0], 'POS')] +Simple details , crafted aluminium and real glass make this laptop blow away the other plastic ridden , bulky sticker filled laptops . .#### #### ####[([1], [0], 'POS'), ([7], [6], 'POS')] +First of all yes this is a mac and it has that nice brushed aluminum . .#### #### ####[([14], [12], 'POS')] +No HDMI port . .#### #### ####[([1, 2], [0], 'NEG')] +Customization on mac is impossible . .#### #### ####[([0], [4], 'NEG')] +Plus two finger clicking as a replacement for the right click button is surprisingly intuitive . .#### #### ####[([9, 11], [14], 'POS')] +The SuperDrive is quiet . .#### #### ####[([1], [3], 'NEG')] +The battery was completely dead , in fact it had grown about a quarter inch thick lump on the underside . .#### #### ####[([1], [4], 'NEG')] +if yo like practicality this is the laptop for you . .#### #### ####[] +The OS is great . .#### #### ####[([1], [3], 'POS')] +CONS : Price is a bit ridiculous , kinda heavy . .#### #### ####[([2], [6], 'NEG'), ([2], [9], 'NEG')] +Which it did not have , only 3 USB 2 ports . .#### #### ####[] +No startup disk was not included but that may be my fault . .#### #### ####[([1, 2], [0], 'NEG'), ([1, 2], [4, 5], 'NEG'), ([1, 2], [11], 'NEG')] +It is very fast and has everything that I need except for a word program . .#### #### ####[([13, 14], [3], 'NEU')] +Needs a CD/DVD drive and a bigger power switch . .#### #### ####[([7, 8], [6], 'POS')] +My laptop with Windows 7 crashed and I did not want Windows 8 . .#### #### ####[([3, 4], [5], 'NEG')] +Easy to install also small to leave anywhere at your bedroom also very easy to configure for ADSl cable or wifi . .#### #### ####[([2], [0], 'POS'), ([15], [13], 'POS'), ([17, 18], [13], 'POS')] +Nice packing . .#### #### ####[([1], [0], 'POS')] +I switched to this because I wanted something different , even though I miss windows . .#### #### ####[([14], [13], 'NEG')] +Apple no longer includes iDVD with the computer and furthermore , Apple does n't even offer it anymore ! .#### #### ####[([4], [1, 3], 'NEU')] +I also wanted Windows 7 , which this one has . .#### #### ####[] +At first , I feel a little bit uncomfortable in using the Mac system . .#### #### ####[([12, 13], [8], 'NEG')] +It just works out of the box and you have a lot of cool software included with the OS . .#### #### ####[([14], [13], 'POS'), ([18], [13], 'POS')] +its as advertised on here ... .. it works great and is not a waste of money ! .#### #### ####[([8], [9], 'POS')] +Premium price for the OS more than anything else . .#### #### ####[([1], [0], 'POS'), ([4], [0], 'POS'), ([4], [5], 'POS')] +I was a little concerned about the touch pad based on reviews , but I 've found it fine to work with . .#### #### ####[([7, 8], [18], 'POS')] +However , the experience was great since the OS does not become unstable and the application will simply shutdown and reopen . .#### #### ####[([8], [5], 'POS'), ([8], [10, 12], 'POS')] +The battery is not as shown in the product photos . .#### #### ####[([1], [3, 5], 'NEG')] +Shipping was quick and product described was the product sent and so much more ... .#### #### ####[([0], [2], 'POS')] +the retina display display make pictures i took years ago jaw dropping . .#### #### ####[] +The Mac Mini is probably the simplest example of compact computing out there . .#### #### ####[([10], [9], 'POS')] +Additionally , there is barely a ventilation system in the computer , and even the simple activity of watching videos let alone playing steam games causes the laptop to get very very hot , and in fact impossible to keep on lap . .#### #### ####[([6, 7], [4], 'NEG')] +Chatting with Acer support , I was advised the problem was corrupted operating system files . .#### #### ####[([12, 14], [11], 'NEG')] +It 's been a couple weeks since the purchase and I 'm struggle with finding the correct keys ( but that was expected ) . .#### #### ####[([17], [12], 'NEG')] +Many people complain about the new OS , and it 's urgent for Apple to fix it asap ! .#### #### ####[([6], [5], 'NEG')] +Now that I have upgraded to Lion I am much happier about MAC OS and have just bought an iMac for office . .#### #### ####[([12, 13], [10], 'POS'), ([19], [10], 'NEU')] +User upgradeable RAM and HDD . .#### #### ####[] +But I wanted the Pro for the CD/DVD player . .#### #### ####[] +I was a little worry at first because I do n't have a lot of experience with os.x and windows has always been second nature to me after many years of using windows . .#### #### ####[] +With the softwares supporting the use of other OS makes it much better . .#### #### ####[([2], [12], 'POS'), ([8], [12], 'NEU')] +I was considering buying the Air , but in reality , this one has a more powerful performance and seems much more convenient , even though it 's about .20 inch thicker and 2 lbs heavier . .#### #### ####[([17], [16], 'POS')] +At home and the office it gets plugged into an external 24 '' LCD screen , so built in screen size is not terribly important . .#### #### ####[([17, 20], [22, 24], 'NEU'), ([19, 20], [22, 24], 'NEU')] +Just beware no DVD slot so when I went to install software I had on CD I could n't . .#### #### ####[([3, 4], [2], 'NEG')] +No Cd Rom in the new version there 's no way I 'm spending that kind of money on something has less features than the older version . .#### #### ####[([1, 2], [0], 'NEG'), ([22], [21], 'NEG')] +the volume is really low to low for a laptopwas not expectin t volume to be so lowan i hate that about this computer .#### #### ####[([1], [4], 'NEG')] +and its not hard to accidentally bang it against something so i recommend getting a case to protect it . .#### #### ####[([15], [2, 3], 'NEU'), ([15], [12], 'POS')] +I got this at an amazing price from Amazon and it arrived just in time . .#### #### ####[([6], [5], 'POS')] +Every time I log into the system after a few hours , there is this endlessly frustrating process that I have to go through . .#### #### ####[([6], [16], 'NEG'), ([17], [16], 'NEG')] +Put a SSD and use a 21 '' LED screen , this set up is silky smooth ! .#### #### ####[([12, 13], [16], 'POS')] +The case is now slightly larger than the previous generation , but the lack of an external power supply justifies the small increase in size . .#### #### ####[([1], [5], 'NEG'), ([16, 18], [13], 'NEG')] +I had to buy a wireless mouse to go with it , as I am old school and hate the pad , but knew that before I bought it , now it works great , need to get adjusted to the key board , as I am used to a bigger one and pounding . .#### #### ####[([20], [18], 'NEG')] +Has all the other features I wanted including a VGA port , HDMI , ethernet and 3 USB ports . .#### #### ####[] +The only thing I dislike about this laptop are the rubber pads found on the bottom of the computer for grip . .#### #### ####[([10, 11], [4], 'NEG'), ([20], [4], 'NEG')] +It 's a decent computer for the price and hopefully it will last a long time . .#### #### ####[([7], [3], 'POS')] +The nicest part is the low heat output and ultra quiet operation . .#### #### ####[([6, 7], [5], 'POS'), ([11], [10], 'POS')] +this Mac Mini does not have a built-in mic , and it would seem that its Mac OS 10.9 does not handle external microphones properly . .#### #### ####[] +A lot of features and shortcuts on the MBP that I was never exposed to on a normal PC . .#### #### ####[] +Was n't sure if I was going to like it much less love it so I went to a local best buy and played around with the IOS system on a Mac Pro and it was totally unique and different . .#### #### ####[([27, 28], [37], 'POS'), ([27, 28], [39], 'POS')] +air has higher resolution but the fonts are small . .#### #### ####[([3], [2], 'NEG'), ([6], [8], 'NEG')] +working with Mac is so much easier , so many cool features . .#### #### ####[([11], [10], 'POS')] +I like the brightness and adjustments . .#### #### ####[([3], [1], 'POS'), ([5], [1], 'POS')] +I only wish this mac had a CD/DVD player built in . .#### #### ####[] +The only thing I miss is that my old Alienware laptop had backlit keys . .#### #### ####[] +So happy with this purchase , I just wish it came with Microsoft Word . .#### #### ####[] +It has enough memory and speed to run my business with all the flexibility that comes with a laptop . .#### #### ####[([3], [2], 'POS'), ([5], [2], 'POS')] +The battery life is excellent , the display is excellent , and downloading apps is a breeze . .#### #### ####[([1, 2], [4], 'POS'), ([7], [4], 'POS'), ([7], [9], 'POS'), ([12, 13], [16], 'POS')] +The screen , the software and the smoothness of the operating system . .#### #### ####[([10, 11], [7], 'POS')] +But with this laptop , the bass is very weak and the sound comes out sounding tinny . .#### #### ####[([6], [9], 'NEG')] +The built quality is really good , I was so Happy and excited about this Product . .#### #### ####[([1, 2], [5], 'POS'), ([1, 2], [10], 'POS'), ([1, 2], [12], 'POS')] +I am loving the fast performance also . .#### #### ####[([5], [2], 'POS'), ([5], [4], 'POS')] +Further , this Mac Mini has a sloppy Bluetooth interface ( courtesy of the Mac OS ) and the range is poor . .#### #### ####[([8, 9], [7], 'NEG'), ([19], [21], 'NEG')] +My only gripe would be the need to add more RAM . .#### #### ####[([10], [9], 'NEU')] +Fine if you have a touch screen . .#### #### ####[([5, 6], [0], 'NEU')] +This by far beats any computer out on the market today built well , battery life AMAZING . .#### #### ####[([11], [12], 'POS'), ([14, 15], [16], 'POS')] +The OS is easy , and offers all kinds of surprises . .#### #### ####[([1], [3], 'POS')] +A veryimportant feature is Firewire 800 which in my experience works better then USB3 ( in PC enabled with USB3 ) I was not originally sold on the MAC OS I felt it was inferior in many ways To Windows 7 . .#### #### ####[([2], [1], 'POS'), ([2], [11], 'POS'), ([4, 5], [11], 'POS'), ([4, 5], [34], 'NEU'), ([28, 29], [34], 'NEU')] +I like iTunes , the apparent security , the Mini form factor , all the nice graphics stuff . .#### #### ####[([2], [1], 'POS')] +After replacing the spinning hard disk with an ssd drive , my mac is just flying . .#### #### ####[([3, 5], [1], 'NEU'), ([8, 9], [1], 'NEU')] +I know some people complained about HDMI issues but they released a firmware patch to address that issue . .#### #### ####[([6], [7], 'NEG')] +With the needs of a professional photographer I generally need to keep up with the best specs . .#### #### ####[([16], [15], 'POS')] +packing and everything was perfect .#### #### ####[([0], [4], 'POS')] +I called Toshiba where I gave them the serial number and they informed me that they were having issues with the mother boards . .#### #### ####[([21, 22], [18], 'NEG')] +I seem to be having repeat problems as the Mother Board in this one is diagnosed as faulty , related to the graphics card . .#### #### ####[([9, 10], [6], 'NEG'), ([9, 10], [17], 'NEG'), ([22, 23], [17], 'NEG')] +It also comes with 4G of RAM but if you 're like me you want to max that out so I immediately put 8G of RAM in her and I 've never used a computer that performs better . .#### #### ####[([36], [37], 'POS')] +This computer is also awesome for my sons virtual home schooling . .#### #### ####[([9, 10], [4], 'POS')] +Cost is more as compared to other brands . .#### #### ####[] +also ... - excellent operating system -- size and weight for optimal mobility -- excellent durability of the battery -- the functions provided by the trackpad is unmatched by any other brand- .#### #### ####[([4, 5], [3], 'POS'), ([7], [3], 'POS'), ([9], [11], 'POS'), ([12], [11], 'POS'), ([15], [14], 'POS')] +This hardware seems to be better than the iMac in that it is n't $ 1400 and smaller . .#### #### ####[([1], [5], 'POS')] +I 've had it for about 2 months now and found no issues with software or updates . .#### #### ####[([14], [11, 12], 'POS'), ([16], [11, 12], 'POS')] +the latest version does not have a disc drive . .#### #### ####[([7, 8], [4, 5], 'NEG')] +Screen - although some people might complain about low res which I think is ridiculous . .#### #### ####[([9], [8], 'NEG')] diff --git a/pred/14lap/14lap_pred_seed18_formatted.csv b/pred/14lap/14lap_pred_seed18_formatted.csv new file mode 100644 index 0000000..8e32523 --- /dev/null +++ b/pred/14lap/14lap_pred_seed18_formatted.csv @@ -0,0 +1,329 @@ +Sentences,"[Aspect, Opinion, Sentiment]" +"Boot time is super fast , around anywhere from 35 seconds to 1 minute .","['Boot time', 'fast', 'POS']" +tech support would not fix the problem unless I bought your plan for $ 150 plus .,[] +Set up was easy .,"['Set up', 'easy', 'POS']" +Did not enjoy the new Windows 8 and touchscreen functions .,"['Windows 8', 'Did not enjoy', 'NEG']","['Windows 8', 'new', 'NEU']" +"Other than not being a fan of click pads ( industry standard these days ) and the lousy internal speakers , it 's hard for me to find things about this notebook I do n't like , especially considering the $ 350 price tag .","['internal speakers', 'lousy', 'NEG']" +"It 's fast , light , and simple to use .","['use', 'fast', 'POS']","['use', 'light', 'POS']","['use', 'simple', 'POS']" +"Works well , and I am extremely happy to be back to an apple OS .","['Works', 'well', 'POS']","['apple OS', 'happy', 'NEU']" +Sure it 's not light and slim but the features make up for it 100 % .,"['features', 'make up', 'POS']" +"I am pleased with the fast log on , speedy WiFi connection and the long battery life ( > 6 hrs ) .","['log', 'fast', 'POS']","['WiFi connection', 'speedy', 'POS']","['battery life', 'long', 'POS']" +The Apple engineers have not yet discovered the delete key .,[] +Made interneting ( part of my business ) very difficult to maintain .,[] +"Luckily , for all of us contemplating the decision , the Mac Mini is priced just right .","['priced', 'right', 'POS']" +"Only problem that I had was that the track pad was not very good for me , I only had a problem once or twice with it , But probably my computer was a bit defective .","['track pad', 'problem', 'NEG']","['track pad', 'not very good', 'NEG']" +It is super fast and has outstanding graphics .,"['graphics', 'outstanding', 'POS']" +But the mountain lion is just too slow .,"['mountain lion', 'slow', 'NEG']" +Strong build though which really adds to its durability .,"['build', 'Strong', 'POS']","['build', 'adds', 'POS']","['durability', 'adds', 'POS']" +The battery life is excellent -- 6-7 hours without charging .,"['battery life', 'excellent', 'POS']" +I 've had my computer for 2 weeks already and it works perfectly .,"['works', 'perfectly', 'POS']" +And I may be the only one but I am really liking Windows 8 .,"['Windows 8', 'liking', 'POS']" +The baterry is very longer .,"['baterry', 'longer', 'NEG']" +Its size is ideal and the weight is acceptable .,"['size', 'ideal', 'POS']","['weight', 'acceptable', 'POS']" +I can say that I am fully satisfied with the performance that the computer has supplied .,"['performance', 'satisfied', 'POS']" +It has so much more speed and the screen is very sharp .,"['speed', 'more', 'POS']","['screen', 'sharp', 'NEG']" +Everything I wanted and everything I needed and the price was great !,"['price', 'great', 'POS']" +It 's not inexpensive but the Hardware performance is impressive for a computer this small .,"['Hardware performance', 'impressive', 'POS']" +"This thing is awesome , everything always works , everything is always easy to set up , everything is compatible , its literally everything I could ask for .","['set up', 'easy', 'POS']","['set up', 'compatible', 'POS']" +Keyboard responds well to presses .,"['Keyboard', 'well', 'POS']" +"Lastly , Windows 8 is annoying .","['Windows 8', 'annoying', 'NEG']" +Everything is so easy and intuitive to setup or configure .,"['setup', 'easy', 'POS']","['configure', 'easy', 'POS']","['setup', 'intuitive', 'POS']","['configure', 'intuitive', 'POS']" +Biggest complaint is Windows 8 .,"['Windows 8', 'complaint', 'NEG']" +Only 2 usb ports ... seems kind of ... limited .,"['usb ports', 'limited', 'NEG']" +It has all the expected features and more +plus a wide screen and more than roomy keyboard .,"['features', 'expected', 'POS']","['screen', 'wide', 'POS']" +Amazing Performance for anything I throw at it .,"['Performance', 'Amazing', 'POS']" +The receiver was full of superlatives for the quality and performance .,"['receiver', 'superlatives', 'POS']","['quality', 'superlatives', 'POS']","['performance', 'superlatives', 'POS']" +I was extremely happy with the OS itself .,"['OS', 'happy', 'POS']" +The new MBP offers great portability and gives us confidence that we are not going to need to purchase a new laptop in 18 months .,"['portability', 'great', 'POS']" +"The criticism has waned , and now I 'd be the first to recommend an Air for truly portable computing .","['criticism', 'waned', 'NEG']" +"MS Office 2011 for Mac is wonderful , well worth it .",[] +But the performance of Mac Mini is a huge disappointment .,"['performance', 'disappointment', 'NEG']" +They do n't just look good ; they deliver excellent performance .,"['performance', 'excellent', 'POS']" +I have had it over a year now with out a Glitch of any kind..I love the lit up keys and screen display ... this thing is Fast and clear as can be .,"['lit up keys', 'love', 'POS']","['screen display', 'love', 'POS']","['screen display', 'Fast', 'POS']","['screen display', 'clear', 'POS']" +The Mountain Lion OS is not hard to figure out if you are familiar with Microsoft Windows .,"['Mountain Lion OS', 'not hard', 'POS']" +"However , I can refute that OSX is `` FAST '' .","['OSX', 'FAST', 'POS']" +Enjoy using Microsoft Office !,[] +Incredible graphics and brilliant colors .,"['graphics', 'Incredible', 'POS']","['colors', 'brilliant', 'POS']" +Built-in apps are purely amazing .,"['Built-in apps', 'amazing', 'POS']" +From the speed to the multi touch gestures this operating system beats Windows easily .,"['speed', 'easily', 'POS']","['operating system', 'easily', 'POS']" +I really like the size and I 'm a fan of the ACERS .,"['size', 'like', 'POS']" +I opted for the SquareTrade 3-Year Computer Accidental Protection Warranty ( $ 1500-2000 ) which also support `` accidents '' like drops and spills that are NOT covered by AppleCare .,"['AppleCare', 'NOT covered', 'NEU']" +It 's light and easy to transport .,"['transport', 'easy', 'POS']" +Once you get past learning how to use the poorly designed Windows 8 Set-Up you may feel frustrated .,[] +The aluminum body sure makes it stand out .,"['aluminum body', 'stand out', 'POS']" +"It is very easy to integrate bluetooth devices , and USB devices are recognized almost instantly .","['bluetooth devices', 'easy', 'NEU']","['USB devices', 'easy', 'NEU']" +And the fact that Apple is driving the 13 '' RMBP with the Intel4000 graphic chip seems underpowered ( to me .,[] +Apple removed the DVD drive Firewire port ( will work with adapter ) and put the SDXC slot in a silly position on the back .,"['DVD drive Firewire port', 'removed', 'NEU']","['SDXC slot', 'silly', 'NEU']" +The durability of the laptop will make it worth the money .,"['durability', 'worth', 'POS']" +Well designed and fast .,[] +"But I was completely wrong , this computer is UNBELIEVABLE amazing and easy to use .","['use', 'amazing', 'POS']","['use', 'easy', 'POS']" +Exactly as posted plus a great value .,"['value', 'great', 'POS']" +The specs are pretty good too .,"['specs', 'good', 'POS']" +"Apple is unmatched in product quality , aesthetics , craftmanship , and customer service .","['aesthetics', 'unmatched', 'POS']","['craftmanship', 'unmatched', 'POS']","['customer service', 'unmatched', 'POS']" +It is a great size and amazing windows 8 included !,"['size', 'great', 'POS']","['windows 8', 'amazing', 'POS']" +I do not like too much Windows 8 .,"['Windows 8', 'not like', 'NEG']" +Startup times are incredibly long : over two minutes .,"['Startup times', 'long', 'NEG']" +Also stunning colors and speedy,"['colors', 'stunning', 'POS']","['colors', 'speedy', 'POS']" +great price free shipping what else can i ask for ! !,"['price', 'great', 'POS']","['shipping', 'great', 'POS']","['price', 'free', 'POS']","['shipping', 'free', 'POS']" +This mouse is terrific .,"['mouse', 'terrific', 'POS']" +It is really thick around the battery .,"['battery', 'thick', 'NEG']" +And windows 7 works like a charm .,"['windows 7', 'charm', 'POS']" +": ) Great product , great price , great delivery , and great service .","['price', 'great', 'POS']","['delivery', 'great', 'POS']","['service', 'great', 'POS']" +: ] It arrived so fast and customer service was great .,"['customer service', 'great', 'POS']" +tried windows 8 and hated it ! ! !,"['windows 8', 'hated', 'NEG']" +Set up was a breeze .,"['Set up', 'breeze', 'POS']" +But I do NOT like Win8 .,"['Win8', 'NOT like', 'NEG']" +"I had the same reasons as most PC users : the price , the overbearing restrictions of OSX and lack of support for games .","['OSX', 'lack', 'NEG']","['support', 'lack', 'NEG']","['games', 'lack', 'NEG']" +"I wanted it for it 's mobility and man , this little bad boy is very nice .","['mobility', 'nice', 'POS']" +I found the mini to be : Exceptionally easy to set up,"['set up', 'easy', 'POS']" +The sound is nice and loud ; I do n't have any problems with hearing anything .,"['sound', 'nice', 'POS']","['sound', 'loud', 'POS']","['sound', ""do n't have any problems"", 'POS']" +"It is very slim , the track pad is very much impressed with me .","['track pad', 'impressed', 'POS']" +The settings are not user-friendly either .,"['settings', 'not user-friendly', 'NEG']" +Thank goodness for OpenOffice !,[] +"Awesome form factor , great battery life , wonderful UX .","['form factor', 'Awesome', 'POS']","['battery life', 'great', 'POS']","['UX', 'wonderful', 'POS']" +i love the keyboard and the screen .,"['keyboard', 'love', 'POS']","['screen', 'love', 'POS']" +"However , there are MAJOR issues with the touchpad which render the device nearly useless .","['touchpad', 'issues', 'NEG']","['touchpad', 'useless', 'NEG']","['device', 'useless', 'NEG']" +I 've already upgraded o Mavericks and I am impressed with everything about this computer .,[] +Not as fast as I would have expect for an i5 .,[] +thanks for great service and shipping !,"['service', 'thanks', 'POS']","['service', 'great', 'POS']","['shipping', 'great', 'POS']" +"The performance seems quite good , and built-in applications like iPhoto work great with my phone and camera .","['performance', 'good', 'POS']","['built-in applications', 'great', 'POS']","['iPhoto', 'great', 'POS']" +I did swap out the hard drive for a Samsung 830 SSD which I highly recommend .,"['hard drive', 'swap out', 'NEU']","['hard drive', 'recommend', 'NEU']" +"Yes , that 's a good thing , but it 's made from aluminum that scratches easily .","['aluminum', 'easily', 'POS']","['scratches', 'easily', 'POS']" +I was also informed that the components of the Mac Book were dirty .,"['components', 'dirty', 'NEG']" +"the hardware problems have been so bad , i ca n't wait till it completely dies in 3 years , TOPS !","['hardware', 'problems', 'NEG']","['hardware', 'bad', 'NEG']" +It 's so nice that the battery last so long and that this machine has the snow lion !,"['battery', 'nice', 'POS']","['battery', 'long', 'POS']" +"it 's exactly what i wanted , and it has all the new features and whatnot .","['features', 'new', 'POS']" +"It feels cheap , the keyboard is not very sensitive .","['keyboard', 'not very sensitive', 'NEG']" +"Though please note that sometimes it crashes , and the sound quality isnt superb .","['sound quality', 'isnt superb', 'NEG']" +It is very easy to navigate even for a novice .,"['navigate', 'easy', 'POS']" +"Does everything I need it to , has a wonderful battery life and I could n't be happier .","['battery life', 'wonderful', 'POS']" +Great Performance and Quality .,"['Performance', 'Great', 'POS']","['Quality', 'Great', 'POS']" +"One more thing , this mac does NOT come with restore disks and I am not sure if you can make them direct from the mac like you can with newer PC 's , also the charging cables are made of the same cheap material as the iPhone/iPod touch cables .",[] +The new os is great on my macbook pro !,"['os', 'new', 'POS']","['os', 'great', 'POS']" +"I have experienced no problems , works as anticipated .","['works', 'no problems', 'POS']" +System is running great .,"['System', 'great', 'POS']" +Easy to customize setting and even create your own bookmarks .,"['setting', 'Easy', 'POS']" +"it has all the features that we expected and the price was good , working well so far .","['price', 'good', 'POS']" +The new operating system makes this computer into a super iPad .,"['operating system', 'new', 'POS']" +Easy to set up and go !,"['set up', 'Easy', 'POS']" +I ca n't believe how quiet the hard drive is and how quick this thing boots up .,"['hard drive', 'quiet', 'NEG']","['hard drive', 'quick', 'POS']" +It 's just what we were looking for and it works great .,"['works', 'great', 'POS']" +It 's so quick and responsive that it makes working / surfing on a computer so much more pleasurable !,"['surfing', 'pleasurable', 'POS']" +"It works fine , and all the software seems to run pretty well .","['works', 'fine', 'POS']","['software', 'well', 'POS']" +"I wanted a computer that was quite , fast , and that had overall great performance .","['performance', 'great', 'POS']" +"Harddrive was in poor condition , had to replace it .","['Harddrive', 'poor', 'NEG']" +The on/off switch is a bit obscure in the rear corner .,"['on/off switch', 'obscure', 'NEG']" +My only complaint is the total lack of instructions that come with the mac mini .,"['instructions', 'complaint', 'NEG']","['instructions', 'lack', 'NEG']" +"The only task that this computer would not be good enough for would be gaming , otherwise the integrated Intel 4000 graphics work well for other tasks .","['Intel 4000 graphics', 'integrated', 'NEU']","['Intel 4000 graphics', 'well', 'NEU']" +"I use it mostly for content creation ( Audio , video , photo editing ) and its reliable .","['content creation', 'mostly', 'POS']","['content creation', 'reliable', 'POS']","['photo editing', 'reliable', 'POS']" +Screen is bright and gorgeous .,"['Screen', 'bright', 'POS']","['Screen', 'gorgeous', 'POS']" +"It is robust , with a friendly use as all Apple products .","['use', 'friendly', 'POS']" +It is fast and easy to use .,"['use', 'fast', 'POS']","['use', 'easy', 'POS']" +And the fact that it comes with an i5 processor definitely speeds things up,"['i5 processor', 'speeds things up', 'POS']" +I have been PC for years but this computer is intuitive and its built in features are a great help,"['built in features', 'great help', 'POS']" +"Nice screen , keyboard works great !","['screen', 'Nice', 'POS']","['keyboard', 'Nice', 'POS']","['keyboard', 'great', 'POS']" +I was amazed at how fast the delivery was .,"['delivery', 'amazed', 'POS']","['delivery', 'fast', 'POS']" +The memory was gone and it was not able to be used .,"['memory', 'gone', 'NEG']" +It works great and I am so happy I bought it .,"['works', 'great', 'POS']" +"I like the design and ease of use with the keyboard , plenty of ports .","['design', 'like', 'POS']","['keyboard', 'like', 'POS']","['keyboard', 'plenty', 'POS']","['ports', 'plenty', 'POS']" +it definitely beats my old mac and the service was great .,"['service', 'great', 'POS']" +Web browsing is very quick with Safari browser .,"['Web browsing', 'quick', 'POS']","['Safari browser', 'quick', 'POS']" +I like the lighted screen at night .,"['lighted screen', 'like', 'POS']" +It is really easy to use and it is quick to start up .,"['use', 'easy', 'POS']","['start up', 'quick', 'POS']" +I 've lived with the crashes and slow operation and restarts .,"['operation', 'slow', 'NEG']" +USB3 Peripherals are noticably less expensive than the ThunderBolt ones .,"['USB3 Peripherals', 'expensive', 'NEG']" +"It 's fast , light , and is perfect for media editing , which is mostly why I bought it in the first place .","['media editing', 'perfect', 'POS']" +"The battery lasts as advertised ( give or take 15-20 minutes ) , and the entire user experience is very elegant .","['user experience', 'elegant', 'POS']" +Thanks for the fast shipment and great price .,"['shipment', 'Thanks', 'POS']","['shipment', 'fast', 'POS']","['price', 'great', 'POS']" +"! Excellent performance , usability , presentation and time response .","['performance', 'Excellent', 'POS']","['usability', 'Excellent', 'POS']","['presentation', 'Excellent', 'POS']","['time response', 'Excellent', 'POS']" +The smaller size was a bonus because of space restrictions .,"['size', 'smaller', 'NEG']" +I blame the Mac OS .,"['Mac OS', 'blame', 'NEG']" +I like the operating system .,"['operating system', 'like', 'POS']" +I love the form factor .,"['form factor', 'love', 'POS']" +It 's fast at loading the internet .,"['internet', 'fast', 'NEU']" +So much faster and sleeker looking .,[] +"Unfortunately , it runs XP and Microsoft is dropping support next April .","['support', 'dropping', 'NEG']" +"First off , I really do like my MBP ... once used to the OS it is pretty easy to get around , and the overall build is great ... eg the keyboard is one of the best to type on .","['OS', 'easy', 'POS']","['build', 'great', 'POS']","['keyboard', 'great', 'POS']","['keyboard', 'best', 'POS']" +It is made of such solid construction and since I have never had a Mac using my iPhone helped me get used to the system a bit .,"['construction', 'solid', 'POS']" +Very nice unibody construction .,"['unibody construction', 'nice', 'POS']" +"This Macbook Pro is fast , powerful , and runs super quiet and cool .","['runs', 'quiet', 'POS']","['runs', 'cool', 'POS']" +It 's ok but does n't have a disk drive which I did n't know until after I bought it .,"['disk drive', ""does n't have"", 'NEG']" +"There is no HDMI receptacle , nor is there an SD card slot located anywhere on the device .","['HDMI receptacle', 'no', 'NEG']" +It came in brand new and works perfectly .,"['works', 'perfectly', 'POS']" +"It should n't happen like that , I do n't have any design app open or anything .",[] +MY TRACKPAD IS NOT WORKING .,"['TRACKPAD', 'NOT WORKING', 'NEG']" +"It looks and feels solid , with a flawless finish .","['finish', 'flawless', 'POS']" +Price was higher when purchased on MAC when compared to price showing on PC when I bought this product .,"['Price', 'higher', 'NEG']" +Then the system would many times not power down without a forced power-off .,"['system', 'not', 'NEG']" +The configuration is perfect for my needs .,"['configuration', 'perfect', 'POS']" +and the speakers is the worst ever .,"['speakers', 'worst', 'NEG']" +"Its the best , its got the looks , super easy to use and love all you can do with the trackpad ! ..","['use', 'easy', 'POS']" +Web surfuring is smooth and seamless .,"['Web surfuring', 'smooth', 'POS']","['Web surfuring', 'seamless', 'POS']" +I 'm overall pleased with the interface and the portability of this product .,"['interface', 'pleased', 'POS']","['portability', 'pleased', 'POS']" +"This item is a beautiful piece , it works well , it is easy to carry and handle .","['works', 'well', 'POS']","['carry', 'easy', 'POS']","['handle', 'easy', 'POS']" +"It was also suffering from hardware ( keyboard ) issues , relatively slow performance and shortening battery lifetime .","['hardware', 'suffering', 'NEG']","['keyboard', 'issues', 'NEG']","['performance', 'slow', 'NEG']","['battery lifetime', 'shortening', 'NEG']" +"Runs good and does the job , ca n't complain about that !","['Runs', 'good', 'POS']" +It 's silent and has a very small footprint on my desk .,"['footprint', 'small', 'NEG']" +The exterior is absolutely gorgeous .,"['exterior', 'gorgeous', 'POS']" +"It has a very high performance , just for what I needed for .","['performance', 'high', 'POS']" +Apple is aware of this issue and this is either old stock or a defective design involving the intel 4000 graphics chipset .,"['design', 'defective', 'NEG']" +"I just bought the new MacBook Pro , the 13 '' model , and I ca n't believe Apple keeps making the same mistake with regard to USB ports .","['USB ports', 'mistake', 'NEU']" +It is the perfect size and speed for me .,"['size', 'perfect', 'POS']","['speed', 'perfect', 'POS']" +THE CUSTOMER SERVICE IS TERRIFIC ! !,"['CUSTOMER SERVICE', 'TERRIFIC', 'POS']" +"My last laptop was a 17 '' ASUS gaming machine , which performed admirably , but having since built my own desktop and really settling into the college life , I found myself wanting something smaller and less cumbersome , not to mention that the ASUS had been slowly developing problems ever since I bought it about 4 years ago .","['performed', 'admirably', 'POS']" +"However , it did not have any scratches , ZERO battery cycle count ( pretty surprised ) , and all the hardware seemed to be working perfectly .","['battery cycle count', 'ZERO', 'NEG']","['hardware', 'perfectly', 'POS']" +And as for all the fancy finger swipes -- I just gave up and attached a mouse .,"['finger swipes', 'fancy', 'NEG']" +"I needed a laptop with big storage , a nice screen and fast so I can photoshop without any problem .","['storage', 'big', 'POS']","['screen', 'nice', 'POS']","['screen', 'fast', 'POS']" +I like coming back to Mac OS but this laptop is lacking in speaker quality compared to my $ 400 old HP laptop .,"['speaker quality', 'lacking', 'NEG']" +Shipped very quickly and safely .,"['Shipped', 'quickly', 'POS']","['Shipped', 'safely', 'POS']" +The thunderbolt port is awesome !,"['thunderbolt port', 'awesome', 'POS']" +The performance is definitely superior to any computer I 've ever put my hands on .,"['performance', 'superior', 'POS']" +It 's great for streaming video and other entertainment uses .,"['streaming video', 'great', 'POS']","['entertainment uses', 'great', 'POS']" +I like the design and its features but there are somethings I think needs to be improved .,"['design', 'like', 'POS']","['features', 'like', 'POS']" +There were small problems with Mac office .,"['Mac office', 'problems', 'NEG']" +I ordered my 2012 mac mini after being disappointed with spec of the new 27 '' Imacs .,"['spec', 'disappointed', 'NEG']" +"Its fast , easy to use and it looks great .","['use', 'fast', 'POS']","['use', 'easy', 'POS']" +"Performance is much much better on the Pro , especially if you install an SSD on it .","['Performance', 'better', 'POS']" +"Note , however , that any existing MagSafe accessories you have will not work with the MagSafe 2 connection .","['MagSafe accessories', 'not work', 'NEG']","['MagSafe accessories', 'not work with', 'NEG']" +"The only thing I dislike is the touchpad , alot of the times its unresponsive and does things I dont want it too , I would recommend using a mouse with it .","['touchpad', 'dislike', 'NEG']" +"The Mac mini is about 8x smaller than my old computer which is a huge bonus and runs very quiet , actually the fans are n't audible unlike my old pc","['fans', ""are n't audible"", 'NEG']" +I thought the transition would be difficult at best and would take some time to fully familiarize myself with the new Mac ecosystem .,"['Mac ecosystem', 'difficult', 'NEG']" +It 's absolutely wonderful and worth the price !,"['price', 'worth', 'POS']" +I am please with the products ease of use ; out of the box ready ; appearance and functionality .,"['use', 'please', 'POS']","['use', 'ease', 'POS']" +Perfect for all my graphic design classes I 'm taking this year in college : - ),[] +I will not be using that slot again .,[] +"The OS is fast and fluid , everything is organized and it 's just beautiful .","['OS', 'fast', 'POS']","['OS', 'fluid', 'POS']","['OS', 'beautiful', 'POS']" +They are simpler to use .,"['use', 'simpler', 'POS']" +! so nice .. stable .. fast .. now i got my SSD !,"['SSD', 'fast', 'NEU']" +I love the quick start up .,"['start up', 'love', 'POS']","['start up', 'quick', 'POS']" +You just can not beat the functionality of an Apple device .,"['functionality', 'can not beat', 'NEG']" +Yet my mac continues to function properly .,"['function', 'properly', 'POS']" +Graphics are much improved .,"['Graphics', 'improved', 'POS']" +"Here are the things that made me confident with my purchase : Build Quality - Seriously , you ca n't beat a unibody construction .","['Build Quality', 'confident', 'POS']","['unibody construction', 'confident', 'NEU']","['unibody construction', ""ca n't beat"", 'NEG']" +It provides much more flexibility for connectivity .,"['connectivity', 'flexibility', 'POS']" +Mac tutorials do help .,"['Mac tutorials', 'help', 'NEU']" +The technical support was not helpful as well .,"['technical support', 'not helpful', 'NEG']","['technical support', 'not helpful as well', 'NEG']" +I got the new adapter and there was no change .,"['adapter', 'new', 'NEU']" +"Logic board utterly fried , cried , and laid down and died .","['Logic board', 'fried', 'NEG']" +The sound was crappy even when you turn up the volume still the same results .,"['sound', 'crappy', 'NEG']" +OSX Lion is a great performer..extremely fast and reliable .,[] +"Having heard from friends and family about how reliable a Mac product is , I never expected to have an application crash within the first month , but I did .","['application', 'crash', 'NEG']" +The Macbook pro 's physical form is wonderful .,"['physical form', 'wonderful', 'POS']" +The Mini 's body has n't changed since late 2010- and for a good reason .,[] +The unibody construction really does feel lot more solid than Apple 's previous laptops .,"['unibody construction', 'solid', 'POS']" +3D rendering slows it down considerably .,[] +"fast , great screen , beautiful apps for a laptop ; priced at 1100 on the apple website ; amazon had it for 1098+ tax - plus i had a 10 % off coupon from amazon-cost me 998 plus tax- 1070- OTD !","['screen', 'fast', 'POS']","['screen', 'great', 'POS']","['apps', 'beautiful', 'POS']" +All the ports are much needed since this is my main computer .,[] +"The Like New condition of the iMac MC309LL/A on Amazon is at $ 900+ level only , and it is a Quad-Core 2.5 GHz CPU ( similar to the $ 799 Mini ) , with Radeon HD 6750M 512MB graphic card ( this mini is integrated Intel 4000 card ) , and it even comes with wireless Apple Keyboard and Mouse , all put together in neat and nice package .","['package', 'nice', 'POS']" +Put a cover on it and is a little better but that is my only complaint .,[] +Within a few hours I was using the gestures unconsciously .,"['gestures', 'unconsciously', 'NEU']" +This mac does come with an extender cable and I 'm using mine right now hoping the cable will stay nice for the many years I plan on using this mac .,"['extender cable', 'nice', 'NEU']","['cable', 'nice', 'POS']" +The 2.9ghz dual-core i7 chip really out does itself .,[] +It is pretty snappy and starts up in about 30 seconds which is good enough for me .,[] +Not sure on Windows 8 .,"['Windows 8', 'Not sure', 'NEG']" +My one complaint is that there was no internal CD drive .,"['internal CD drive', 'complaint', 'NEG']","['internal CD drive', 'no', 'NEG']" +This newer netbook has no hard drive or network lights .,"['hard drive', 'no', 'NEG']" +Not too expense and has enough storage for most users and many ports .,"['storage', 'enough', 'POS']" +The audio volume is quite low and virtually unusable in a room with any background activity .,"['audio volume', 'low', 'NEG']","['audio volume', 'unusable', 'NEG']" +It is lightweight and the perfect size to carry to class .,"['size', 'perfect', 'POS']" +The MBP is beautiful has many wonderful capabilities .,"['MBP', 'beautiful', 'POS']","['capabilities', 'wonderful', 'POS']" +"I thought that it will be fine , if i do some settings .","['settings', 'fine', 'NEU']" +Runs very smoothly .,"['Runs', 'smoothly', 'POS']" +Boot-up slowed significantly after all Windows updates were installed .,"['Boot-up', 'slowed', 'NEG']" +"It was important that it was powerful enough to do all of the tasks he needed on the internet , word processing , graphic design and gaming .","['word processing', 'powerful', 'POS']","['graphic design', 'powerful', 'POS']" +"I like the Mini Mac it was easy to setup and install , but I am learning as I go and could use a tutorial to learn how to use some of the features I was use to on the PC especially the right mouse click menu .","['setup', 'easy', 'POS']" +Runs real quick .,"['Runs', 'quick', 'POS']" +"Since the machine 's slim profile is critical to me , that was a problem .","['profile', 'slim', 'NEG']","['profile', 'critical', 'NEG']" +"WiFi capability , disk drive and multiple USB ports to connect scale and printers was all that was required .",[] +"The SD card reader is slightly recessed and upside down ( the nail slot on the card can not be accessed ) , if this was a self ejecting slot this would not be an issue , but its not .","['SD card reader', 'recessed', 'NEG']","['nail slot', 'recessed', 'NEU']","['nail slot', 'upside down', 'NEU']","['nail slot', 'can not be accessed', 'NEG']" +"Soft touch , anodized aluminum with laser cut precision and no flaws .","['touch', 'Soft', 'POS']" +"Simple details , crafted aluminium and real glass make this laptop blow away the other plastic ridden , bulky sticker filled laptops .","['details', 'Simple', 'POS']","['glass', 'real', 'POS']" +First of all yes this is a mac and it has that nice brushed aluminum .,"['aluminum', 'nice', 'POS']" +No HDMI port .,"['HDMI port', 'No', 'NEG']" +Customization on mac is impossible .,"['Customization', 'impossible', 'NEG']" +Plus two finger clicking as a replacement for the right click button is surprisingly intuitive .,"['right click button', 'intuitive', 'POS']" +The SuperDrive is quiet .,"['SuperDrive', 'quiet', 'NEG']" +"The battery was completely dead , in fact it had grown about a quarter inch thick lump on the underside .","['battery', 'dead', 'NEG']" +if yo like practicality this is the laptop for you .,[] +The OS is great .,"['OS', 'great', 'POS']" +"CONS : Price is a bit ridiculous , kinda heavy .","['Price', 'ridiculous', 'NEG']","['Price', 'heavy', 'NEG']" +"Which it did not have , only 3 USB 2 ports .",[] +No startup disk was not included but that may be my fault .,"['startup disk', 'No', 'NEG']","['startup disk', 'not included', 'NEG']","['startup disk', 'fault', 'NEG']" +It is very fast and has everything that I need except for a word program .,"['word program', 'fast', 'NEU']" +Needs a CD/DVD drive and a bigger power switch .,"['power switch', 'bigger', 'POS']" +My laptop with Windows 7 crashed and I did not want Windows 8 .,"['Windows 7', 'crashed', 'NEG']" +Easy to install also small to leave anywhere at your bedroom also very easy to configure for ADSl cable or wifi .,"['install', 'Easy', 'POS']","['configure', 'easy', 'POS']","['ADSl cable', 'easy', 'POS']" +Nice packing .,"['packing', 'Nice', 'POS']" +"I switched to this because I wanted something different , even though I miss windows .","['windows', 'miss', 'NEG']" +"Apple no longer includes iDVD with the computer and furthermore , Apple does n't even offer it anymore !","['iDVD', 'no longer includes', 'NEU']" +"I also wanted Windows 7 , which this one has .",[] +"At first , I feel a little bit uncomfortable in using the Mac system .","['Mac system', 'uncomfortable', 'NEG']" +It just works out of the box and you have a lot of cool software included with the OS .,"['software', 'cool', 'POS']","['OS', 'cool', 'POS']" +its as advertised on here ... .. it works great and is not a waste of money !,"['works', 'great', 'POS']" +Premium price for the OS more than anything else .,"['price', 'Premium', 'POS']","['OS', 'Premium', 'POS']","['OS', 'more', 'POS']" +"I was a little concerned about the touch pad based on reviews , but I 've found it fine to work with .","['touch pad', 'fine', 'POS']" +"However , the experience was great since the OS does not become unstable and the application will simply shutdown and reopen .","['OS', 'great', 'POS']","['OS', 'not become unstable', 'POS']" +The battery is not as shown in the product photos .,"['battery', 'not as shown', 'NEG']" +Shipping was quick and product described was the product sent and so much more ...,"['Shipping', 'quick', 'POS']" +the retina display display make pictures i took years ago jaw dropping .,[] +The Mac Mini is probably the simplest example of compact computing out there .,"['computing', 'compact', 'POS']" +"Additionally , there is barely a ventilation system in the computer , and even the simple activity of watching videos let alone playing steam games causes the laptop to get very very hot , and in fact impossible to keep on lap .","['ventilation system', 'barely', 'NEG']" +"Chatting with Acer support , I was advised the problem was corrupted operating system files .","['operating system files', 'corrupted', 'NEG']" +It 's been a couple weeks since the purchase and I 'm struggle with finding the correct keys ( but that was expected ) .,"['keys', 'struggle', 'NEG']" +"Many people complain about the new OS , and it 's urgent for Apple to fix it asap !","['OS', 'new', 'NEG']" +Now that I have upgraded to Lion I am much happier about MAC OS and have just bought an iMac for office .,"['MAC OS', 'happier', 'POS']","['iMac', 'happier', 'NEU']" +User upgradeable RAM and HDD .,[] +But I wanted the Pro for the CD/DVD player .,[] +I was a little worry at first because I do n't have a lot of experience with os.x and windows has always been second nature to me after many years of using windows .,[] +With the softwares supporting the use of other OS makes it much better .,"['softwares', 'better', 'POS']","['OS', 'better', 'NEU']" +"I was considering buying the Air , but in reality , this one has a more powerful performance and seems much more convenient , even though it 's about .20 inch thicker and 2 lbs heavier .","['performance', 'powerful', 'POS']" +"At home and the office it gets plugged into an external 24 '' LCD screen , so built in screen size is not terribly important .","['built in screen size', 'not terribly important', 'NEU']","['screen size', 'not terribly important', 'NEU']" +Just beware no DVD slot so when I went to install software I had on CD I could n't .,"['DVD slot', 'no', 'NEG']" +No Cd Rom in the new version there 's no way I 'm spending that kind of money on something has less features than the older version .,"['Cd Rom', 'No', 'NEG']","['features', 'less', 'NEG']" +the volume is really low to low for a laptopwas not expectin t volume to be so lowan i hate that about this computer,"['volume', 'low', 'NEG']" +and its not hard to accidentally bang it against something so i recommend getting a case to protect it .,"['case', 'not hard', 'NEU']","['case', 'recommend', 'POS']" +I got this at an amazing price from Amazon and it arrived just in time .,"['price', 'amazing', 'POS']" +"Every time I log into the system after a few hours , there is this endlessly frustrating process that I have to go through .","['system', 'frustrating', 'NEG']","['process', 'frustrating', 'NEG']" +"Put a SSD and use a 21 '' LED screen , this set up is silky smooth !","['set up', 'smooth', 'POS']" +"The case is now slightly larger than the previous generation , but the lack of an external power supply justifies the small increase in size .","['case', 'larger', 'NEG']","['external power supply', 'lack', 'NEG']" +"I had to buy a wireless mouse to go with it , as I am old school and hate the pad , but knew that before I bought it , now it works great , need to get adjusted to the key board , as I am used to a bigger one and pounding .","['pad', 'hate', 'NEG']" +"Has all the other features I wanted including a VGA port , HDMI , ethernet and 3 USB ports .",[] +The only thing I dislike about this laptop are the rubber pads found on the bottom of the computer for grip .,"['rubber pads', 'dislike', 'NEG']","['grip', 'dislike', 'NEG']" +It 's a decent computer for the price and hopefully it will last a long time .,"['price', 'decent', 'POS']" +The nicest part is the low heat output and ultra quiet operation .,"['heat output', 'low', 'POS']","['operation', 'quiet', 'POS']" +"this Mac Mini does not have a built-in mic , and it would seem that its Mac OS 10.9 does not handle external microphones properly .",[] +A lot of features and shortcuts on the MBP that I was never exposed to on a normal PC .,[] +Was n't sure if I was going to like it much less love it so I went to a local best buy and played around with the IOS system on a Mac Pro and it was totally unique and different .,"['IOS system', 'unique', 'POS']","['IOS system', 'different', 'POS']" +air has higher resolution but the fonts are small .,"['resolution', 'higher', 'NEG']","['fonts', 'small', 'NEG']" +"working with Mac is so much easier , so many cool features .","['features', 'cool', 'POS']" +I like the brightness and adjustments .,"['brightness', 'like', 'POS']","['adjustments', 'like', 'POS']" +I only wish this mac had a CD/DVD player built in .,[] +The only thing I miss is that my old Alienware laptop had backlit keys .,[] +"So happy with this purchase , I just wish it came with Microsoft Word .",[] +It has enough memory and speed to run my business with all the flexibility that comes with a laptop .,"['memory', 'enough', 'POS']","['speed', 'enough', 'POS']" +"The battery life is excellent , the display is excellent , and downloading apps is a breeze .","['battery life', 'excellent', 'POS']","['display', 'excellent', 'POS']","['display', 'excellent', 'POS']","['downloading apps', 'breeze', 'POS']" +"The screen , the software and the smoothness of the operating system .","['operating system', 'smoothness', 'POS']" +"But with this laptop , the bass is very weak and the sound comes out sounding tinny .","['bass', 'weak', 'NEG']" +"The built quality is really good , I was so Happy and excited about this Product .","['built quality', 'good', 'POS']","['built quality', 'Happy', 'POS']","['built quality', 'excited', 'POS']" +I am loving the fast performance also .,"['performance', 'loving', 'POS']","['performance', 'fast', 'POS']" +"Further , this Mac Mini has a sloppy Bluetooth interface ( courtesy of the Mac OS ) and the range is poor .","['Bluetooth interface', 'sloppy', 'NEG']","['range', 'poor', 'NEG']" +My only gripe would be the need to add more RAM .,"['RAM', 'more', 'NEU']" +Fine if you have a touch screen .,"['touch screen', 'Fine', 'NEU']" +"This by far beats any computer out on the market today built well , battery life AMAZING .","['built', 'well', 'POS']","['battery life', 'AMAZING', 'POS']" +"The OS is easy , and offers all kinds of surprises .","['OS', 'easy', 'POS']" +A veryimportant feature is Firewire 800 which in my experience works better then USB3 ( in PC enabled with USB3 ) I was not originally sold on the MAC OS I felt it was inferior in many ways To Windows 7 .,"['feature', 'veryimportant', 'POS']","['feature', 'better', 'POS']","['Firewire 800', 'better', 'POS']","['Firewire 800', 'inferior', 'NEU']","['MAC OS', 'inferior', 'NEU']" +"I like iTunes , the apparent security , the Mini form factor , all the nice graphics stuff .","['iTunes', 'like', 'POS']" +"After replacing the spinning hard disk with an ssd drive , my mac is just flying .","['spinning hard disk', 'replacing', 'NEU']","['ssd drive', 'replacing', 'NEU']" +I know some people complained about HDMI issues but they released a firmware patch to address that issue .,"['HDMI', 'issues', 'NEG']" +With the needs of a professional photographer I generally need to keep up with the best specs .,"['specs', 'best', 'POS']" +packing and everything was perfect,"['packing', 'perfect', 'POS']" +I called Toshiba where I gave them the serial number and they informed me that they were having issues with the mother boards .,"['mother boards', 'issues', 'NEG']" +"I seem to be having repeat problems as the Mother Board in this one is diagnosed as faulty , related to the graphics card .","['Mother Board', 'problems', 'NEG']","['Mother Board', 'faulty', 'NEG']","['graphics card', 'faulty', 'NEG']" +It also comes with 4G of RAM but if you 're like me you want to max that out so I immediately put 8G of RAM in her and I 've never used a computer that performs better .,"['performs', 'better', 'POS']" +This computer is also awesome for my sons virtual home schooling .,"['home schooling', 'awesome', 'POS']" +Cost is more as compared to other brands .,[] +also ... - excellent operating system -- size and weight for optimal mobility -- excellent durability of the battery -- the functions provided by the trackpad is unmatched by any other brand-,"['operating system', 'excellent', 'POS']","['size', 'excellent', 'POS']","['weight', 'optimal', 'POS']","['mobility', 'optimal', 'POS']","['durability', 'excellent', 'POS']" +This hardware seems to be better than the iMac in that it is n't $ 1400 and smaller .,"['hardware', 'better', 'POS']" +I 've had it for about 2 months now and found no issues with software or updates .,"['software', 'no issues', 'POS']","['updates', 'no issues', 'POS']" +the latest version does not have a disc drive .,"['disc drive', 'not have', 'NEG']" +Screen - although some people might complain about low res which I think is ridiculous .,"['res', 'low', 'NEG']" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..3d418f6 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,14 @@ +Cython==0.29.21 +PYEVALB==0.1.3 +allennlp-models==1.2.2 +allennlp==1.2.2 +botocore==1.19.46 +fire==0.3.1 +nltk==3.6.6 +numpy==1.21.5 +pandas==1.1.5 +pydantic==1.6.2 +scikit-learn==0.22.2.post1 +torch==1.7.0 +torchvision==0.8.1n +transformers==3.4.0 diff --git a/semple_data.txt b/semple_data.txt new file mode 100644 index 0000000..2486acb --- /dev/null +++ b/semple_data.txt @@ -0,0 +1,100 @@ +I charge it at night and skip taking the cord with me because of the good battery life .#### #### ####[([16, 17], [15], 'POS')] +it is of high quality , has a killer GUI , is extremely stable , is highly expandable , is bundled with lots of very good applications , is easy to use , and is absolutely gorgeous .#### #### ####[([4], [3], 'POS'), ([9], [8], 'POS'), ([26], [25], 'POS'), ([31], [29], 'POS')] +Easy to start up and does not overheat as much as other laptops .#### #### ####[([2, 3], [0], 'POS')] +Great laptop that offers many great features !#### #### ####[([6], [5], 'POS')] +One night I turned the freaking thing off after using it , the next day I turn it on , no GUI , screen all dark , power light steady , hard drive light steady and not flashing as it usually does .#### #### ####[([21], [20], 'NEG'), ([23], [25], 'NEG'), ([27, 28], [29], 'NEU'), ([31, 32, 33], [34], 'NEG')] +However , the multi-touch gestures and large tracking area make having an external mouse unnecessary ( unless you 're gaming ) .#### #### ####[([12, 13], [14], 'NEU')] +I love the way the entire suite of software works together .#### #### ####[([6, 7, 8], [1], 'POS')] +The speed is incredible and I am more than satisfied .#### #### ####[([1], [3], 'POS'), ([1], [9], 'POS')] +I can barely use any usb devices because they will not stay connected properly .#### #### ####[([5, 6], [10, 11, 12, 13], 'NEG')] +When I finally had everything running with all my software installed I plugged in my droid to recharge and the system crashed .#### #### ####[([20], [21], 'NEG')] +Pairing it with an iPhone is a pure pleasure - talk about painless syncing - used to take me forever - now it 's a snap .#### #### ####[([13], [12], 'POS')] +I also got the added bonus of a 30 '' HD Monitor , which really helps to extend my screen and keep my eyes fresh !#### #### ####[([19], [17], 'NEU')] +The machine is slow to boot up and occasionally crashes completely .#### #### ####[([5, 6], [3], 'NEG')] +After paying several hundred dollars for this service , it is frustrating that you can not get help after hours .#### #### ####[([7], [11], 'NEG')] +I love the operating system and the preloaded software .#### #### ####[([3, 4], [1], 'POS'), ([7, 8], [1], 'POS')] +The best thing about this laptop is the price along with some of the newer features .#### #### ####[([8], [1], 'POS'), ([15], [1], 'POS'), ([15], [14], 'POS')] +YOU WILL NOT BE ABLE TO TALK TO AN AMERICAN WARRANTY SERVICE IS OUT OF COUNTRY .#### #### ####[([10, 11], [2, 3, 4], 'NEG')] +but now i have realized its a problem with this brand .#### #### ####[([10], [7], 'NEG')] +Also kinda loud when the fan was running .#### #### ####[([5], [2], 'NEG')] +There also seemed to be a problem with the hard disc as certain times windows loads but claims to not be able to find any drivers or files .#### #### ####[([9, 10], [6], 'NEG')] +Speaking of the browser , it too has problems .#### #### ####[([3], [8], 'NEG')] +The keyboard is too slick .#### #### ####[([1], [4], 'NEG')] +It 's like 9 punds , but if you can look past it , it 's GREAT !#### #### ####[([3, 4], [16], 'NEG')] +It 's just as fast with one program open as it is with sixteen open .#### #### ####[([7], [4], 'NEU')] +Still under warrenty so called Toshiba , no help at all .#### #### ####[([2], [7, 8], 'NEG')] +Amazing Quality !#### #### ####[([1], [0], 'POS')] +A month or so ago , the freaking motherboard just died .#### #### ####[([8], [7], 'NEG'), ([8], [10], 'NEG')] +The system it comes with does not work properly , so when trying to fix the problems with it it started not working at all .#### #### ####[([1], [6, 7, 8], 'NEG')] +Then after 4 or so months the charger stopped working so I was forced to go out and buy new hardware just to keep this computer running .#### #### ####[([7], [8, 9], 'NEG')] +If a website ever freezes ( which is rare ) , its really easy to force quit .#### #### ####[([15, 16], [13], 'POS')] +I also enjoy the fact that my MacBook Pro laptop allows me to run Windows 7 on it by using the VMWare program .#### #### ####[([14, 15], [2], 'POS'), ([21, 22], [2], 'NEU')] +I wanted to purchase the extended warranty and they refused , because they knew it was trouble .#### #### ####[([5, 6], [9], 'NEU')] +We upgraded the memory to four gigabytes in order to take advantage of the performace increase in speed .#### #### ####[([17], [15], 'POS'), ([14], [15], 'POS')] +The reality was , it heated up very quickly , and took way too long to do simple things , like opening my Documents folder .#### #### ####[([21, 22, 23, 24], [14], 'NEG')] +I had always used PCs and been constantly frustrated by the crashing and the poorly designed operating systems that were never very intuitive .#### #### ####[([16, 17], [14, 15], 'NEG'), ([16, 17], [22], 'NEG')] +Then , within 5 months , the charger crapped out on me .#### #### ####[([7], [8], 'NEG')] +And if you have a iphone or ipod touch you can connect and download songs to it at high speed .#### #### ####[([19], [18], 'POS')] +I love the glass touchpad .#### #### ####[([3, 4], [1], 'POS')] +I continued to take the computer in AGAIN and they replaced the hard drive and mother board yet again .#### #### ####[([12, 13], [10], 'NEG'), ([15, 16], [10], 'NEG')] +Then HP sends it back to me with the hardware screwed up , not able to connect .#### #### ####[([9], [10, 11], 'NEG')] +Oh yeah , do n't forget the expensive shipping to and from HP .#### #### ####[([8], [7], 'NEG')] +Everything is so easy to use , Mac software is just so much simpler than Microsoft software .#### #### ####[([7, 8], [3], 'POS'), ([15, 16], [13, 14], 'NEG'), ([5], [3], 'POS')] +And if you do a lot of writing , editing is a problem since there is no forward delete key .#### #### ####[([9], [12], 'NEG')] +Its ease of use and the top service from Apple- be it their phone assistance or bellying up to the genius bar -- can not be beat .#### #### ####[([3], [1], 'POS'), ([7], [6], 'POS'), ([13, 14], [23, 24, 25, 26], 'POS'), ([20, 21], [23, 24, 25, 26], 'POS')] +It has a 10 hour battery life when you 're doing web browsing and word editing , making it perfect for the classroom or office , and in terms of gaming and movie playing it 'll have a battery life of just over 5 hours .#### #### ####[([5, 6], [19], 'POS'), ([11, 12], [19], 'NEU'), ([14, 15], [19], 'NEU')] +Acer has set me up with FREE recovery discs , when they are available since I asked .#### #### ####[([7, 8], [6], 'POS')] +Enabling the battery timer is useless .#### #### ####[([2, 3], [5], 'NEG')] +There is no need to purchase virus protection for Mac , which saves me a lot of time and money .#### #### ####[([6, 7, 8, 9], [12], 'POS')] +But we had paid for bluetooth , and there was none .#### #### ####[([5], [10], 'NEG')] +It is always reliable , never bugged and responds well .#### #### ####[([8], [9], 'POS')] +they had to replace the motherboard in April#### #### ####[([5], [3], 'NEG')] +Also , if you need to talk to a representive at Microsoft , there is a charge , which I believe is robbery , since you are charged enormous amounts for a very badly designed system , which most people would have went with XP if they could .#### #### ####[([35], [33, 34], 'NEG')] +I love WIndows 7 which is a vast improvment over Vista .#### #### ####[([2, 3], [1], 'POS')] +Dell 's customer disservice is an insult to it 's customers who pay good money for shoddy products .#### #### ####[([0, 1, 2, 3], [6], 'NEG')] +After talking it over with the very knowledgeable sales associate , I chose the MacBook Pro over the white MacBook .#### #### ####[([8, 9], [7], 'POS')] +If you really want a bang-up system and do n't need to run Windows applications , go with an Apple ;#### #### ####[([6], [5], 'POS')] +You wo n't have to spend gobs of money on some inefficient virus program that needs to be updated every month and that constantly drains your wallet .#### #### ####[([12, 13], [11], 'NEG')] +It 's color is even cool .#### #### ####[([2], [5], 'POS')] +keys are all in weird places and is way too large for the way it is designed .#### #### ####[([0], [4], 'NEG'), ([0], [10], 'NEG')] +Yes , a Mac is much more money than the average laptop out there , but there is no comparison in style , speed and just cool factor .#### #### ####[([21], [18, 19], 'POS'), ([23], [18, 19], 'POS')] +And not to mention after using it for a few months or so , the battery will slowly less and less hold a charge until you ca n't leave it unplugged for more than 5 minutes without the thing dying .#### #### ####[([15], [18], 'NEG')] +BEST BUY - 5 STARS + + + ( sales , service , respect for old men who are n't familiar with the technology ) DELL COMPUTERS - 3 stars DELL SUPPORT - owes a me a couple#### #### ####[([9], [0], 'POS'), ([11], [0], 'POS')] +no complaints with their desktop , and maybe because it just sits on your desktop , and you do n't carry it around , which could jar the hard drive , or the motherboard .#### #### ####[([28, 29], [26], 'NEU'), ([33], [26], 'NEU')] +Yes , they cost more , but they more than make up for it in speed , construction quality , and longevity .#### #### ####[([15], [10, 11], 'POS'), ([17, 18], [10, 11], 'POS'), ([21], [10, 11], 'POS')] +It absolutely is more expensive than most PC laptops , but the ease of use , security , and minimal problems that have arisen make it well worth the pricetag .#### #### ####[([14], [12], 'POS')] +It gets stuck all of the time you use it , and you have to keep tapping on it to get it to work .#### #### ####[([8], [2], 'NEG')] +lots of preloaded software .#### #### ####[([2, 3], [0], 'POS')] +I wish it had a webcam though , then it would be perfect !#### #### ####[([5], [1], 'NEG')] +Another thing I might add is the battery life is excellent .#### #### ####[([7, 8], [10], 'POS')] +One drawback , I wish the keys were backlit .#### #### ####[([6], [1], 'NEG')] +I wish the volume could be louder and the mouse didnt break after only a month .#### #### ####[([3], [6], 'NEG'), ([9], [10, 11], 'NEG')] +I play a lot of casual games online , and the touchpad is very responsive .#### #### ####[([11], [14], 'POS')] +It is everything I 'd hoped it would be from a look and feel standpoint , but somehow a bit more sturdy .#### #### ####[([11, 12, 13, 14], [21], 'POS')] +the only fact i dont like about apples is they generally use safari and i dont use safari but after i install Mozzilla firfox i love every single bit about it .#### #### ####[([17], [15, 16], 'NEG'), ([22, 23], [25], 'POS')] +Great battery , speed , display .#### #### ####[([1], [0], 'POS'), ([3], [0], 'POS'), ([5], [0], 'POS')] +The delivery was fast , and I would not hesitate to purchase this laptop again .#### #### ####[([1], [3], 'POS')] +I 've been impressed with the battery life and the performance for such a small amount of memory .#### #### ####[([6, 7], [3], 'POS'), ([10], [14], 'POS'), ([17], [14], 'NEG')] +It 's applications are terrific , including the replacements for Microsoft office .#### #### ####[([2], [4], 'POS')] +I got it back and my built-in webcam and built-in mic were shorting out anytime I touched the lid , ( mind you this was my means of communication with my fiance who was deployed ) but I suffered thru it and would constandly have to reset the computer to be able to use my cam and mic anytime they went out .#### #### ####[([6, 7], [12, 13], 'NEG'), ([9, 10], [12, 13], 'NEG'), ([55], [38], 'NEG'), ([10], [38], 'NEG')] +The board has a bad connector with the power supply and shortly after warrenty expires the power supply will start having issues .#### #### ####[([1], [4], 'NEG'), ([5], [4], 'NEG'), ([16, 17], [21], 'NEG')] +My dad has one of the very first Toshibas ever made , yes its abit slow now but still works well and i hooked to my ethernet !#### #### ####[([19], [20], 'POS')] +Mostly I love the drag and drop feature .#### #### ####[([4, 5, 6, 7], [2], 'POS')] +oh yeah , and if the fancy webcam breaks guess who you have to send it to to get it fixed ?#### #### ####[([7], [6], 'NEG')] +I ordered through MacMall , which saved me the sales tax I would have incurred buying locally .#### #### ####[([9, 10], [6], 'POS')] +Of course , I also have several great software packages that came for free including iWork , GarageBand , and iMovie .#### #### ####[([8, 9], [7], 'POS'), ([15], [13], 'POS'), ([17], [13], 'POS'), ([20], [13], 'POS')] +The screen is very large and crystal clear with amazing colors and resolution .#### #### ####[([1], [4], 'POS'), ([1], [7], 'POS'), ([10], [9], 'POS'), ([12], [9], 'POS')] +After a little more than a year of owning my MacBook Pro , the monitor has completely died .#### #### ####[([14], [17], 'NEG')] +The brand of iTunes has just become ingrained in our lexicon now , but keep in mind that Apple started it all .#### #### ####[([3], [7], 'POS')] +Size : I know 13 is small ( especially for a desktop replacement ) but with an external monitor , who cares .#### #### ####[([0], [6], 'NEG'), ([17, 18], [6], 'NEU')] +The display is incredibly bright , much brighter than my PowerBook and very crisp .#### #### ####[([1], [4], 'POS'), ([1], [13], 'POS')] +The start menu is not the easiest thing to navigate due to the stacking .#### #### ####[([1, 2], [4, 5, 6], 'NEG')] +Really like the textured surface which shows no fingerprints .#### #### ####[([4], [1], 'POS')] +The screen is bright and the keyboard is nice ;#### #### ####[([1], [3], 'POS'), ([6], [8], 'POS')] +But the machine is awesome and iLife is great and I love Snow Leopard X .#### #### ####[([6], [8], 'POS'), ([12, 13, 14], [11], 'POS')] +I thought learning the Mac OS would be hard , but it is easily picked up if you are familiar with a PC .#### #### ####[([4, 5], [13], 'POS')] +It is easy to use and lightweight .#### #### ####[([4], [2], 'POS')] +They also have a longer service life than other computers ( I have several friends who still use the older Apple PowerBooks ) .#### #### ####[([5, 6], [4], 'POS')] +If you check you will find the same notebook with the above missing ports and a dual core AMD or Intel processor .#### #### ####[([13], [12], 'NEU')] +This laptop is a great price and has a sleek look .#### #### ####[([5], [4], 'POS'), ([10], [9], 'POS')] +I especially like the keyboard which has chiclet type keys .#### #### ####[([4], [2], 'POS'), ([9], [7, 8], 'POS')] \ No newline at end of file diff --git a/setup.sh b/setup.sh new file mode 100644 index 0000000..0891e9e --- /dev/null +++ b/setup.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -e + +# Main Requirements +pip install -r requirements.txt +pip uninstall dataclasses -y # Compatibility issue with Python > 3.6 + +# Optional: Set up NLTK packages +if [[ -f punkt.zip ]]; then + mkdir -p /home/admin/nltk_data/tokenizers + cp punkt.zip /home/admin/nltk_data/tokenizers +fi +if [[ -f wordnet.zip ]]; then + mkdir -p /home/admin/nltk_data/corpora + cp wordnet.zip /home/admin/nltk_data/corpora +fi + +# Make sample data for quick debugging +unzip -n data.zip -d aste/ +cd aste/data/triplet_data +mkdir -p sample +head -n 32 14lap/train.txt >sample/train.txt +head -n 32 14lap/dev.txt >sample/dev.txt +head -n 32 14lap/test.txt >sample/test.txt +cd ../../.. diff --git a/span_model/__init__.py b/span_model/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/span_model/data/__init__.py b/span_model/data/__init__.py new file mode 100644 index 0000000..d6f82bc --- /dev/null +++ b/span_model/data/__init__.py @@ -0,0 +1,2 @@ +from span_model.data.dataset_readers.span_model import SpanModelReader +from span_model.data.dataset_readers.document import Document diff --git a/span_model/data/dataset_readers/document.py b/span_model/data/dataset_readers/document.py new file mode 100644 index 0000000..9ea8511 --- /dev/null +++ b/span_model/data/dataset_readers/document.py @@ -0,0 +1,427 @@ +from span_model.models.shared import fields_to_batches, batches_to_fields +import copy +import numpy as np +import re +import json + + +def format_float(x): + return round(x, 4) + + +class SpanCrossesSentencesError(ValueError): + pass + + +def get_sentence_of_span(span, sentence_starts, doc_tokens): + """ + Return the index of the sentence that the span is part of. + """ + # Inclusive sentence ends + sentence_ends = [x - 1 for x in sentence_starts[1:]] + [doc_tokens - 1] + in_between = [ + span[0] >= start and span[1] <= end + for start, end in zip(sentence_starts, sentence_ends) + ] + if sum(in_between) != 1: + raise SpanCrossesSentencesError + the_sentence = in_between.index(True) + return the_sentence + + +class Dataset: + def __init__(self, documents): + self.documents = documents + + def __getitem__(self, i): + return self.documents[i] + + def __len__(self): + return len(self.documents) + + def __repr__(self): + return f"Dataset with {self.__len__()} documents." + + @classmethod + def from_jsonl(cls, fname): + documents = [] + with open(fname, "r") as f: + for line in f: + doc = Document.from_json(json.loads(line)) + documents.append(doc) + + return cls(documents) + + def to_jsonl(self, fname): + to_write = [doc.to_json() for doc in self] + with open(fname, "w") as f: + for entry in to_write: + print(json.dumps(entry), file=f) + + +class Document: + def __init__( + self, + doc_key, + dataset, + sentences, + weight=None, + ): + self.doc_key = doc_key + self.dataset = dataset + self.sentences = sentences + self.weight = weight + + @classmethod + def from_json(cls, js): + "Read in from json-loaded dict." + cls._check_fields(js) + doc_key = js["doc_key"] + dataset = js.get("dataset") + entries = fields_to_batches( + js, + [ + "doc_key", + "dataset", + "weight", + ], + ) + sentence_lengths = [len(entry["sentences"]) for entry in entries] + sentence_starts = np.cumsum(sentence_lengths) + sentence_starts = np.roll(sentence_starts, 1) + sentence_starts[0] = 0 + sentence_starts = sentence_starts.tolist() + sentences = [ + Sentence(entry, sentence_start, sentence_ix) + for sentence_ix, (entry, sentence_start) in enumerate( + zip(entries, sentence_starts) + ) + ] + + # Get the loss weight for this document. + weight = js.get("weight", None) + + return cls( + doc_key, + dataset, + sentences, + weight, + ) + + @staticmethod + def _check_fields(js): + "Make sure we only have allowed fields." + allowed_field_regex = ( + "doc_key|dataset|sentences|weight|.*ner$|" + ".*relations$|.*clusters$|.*events$|^_.*" + ) + allowed_field_regex = re.compile(allowed_field_regex) + unexpected = [] + for field in js.keys(): + if not allowed_field_regex.match(field): + unexpected.append(field) + + if unexpected: + msg = f"The following unexpected fields should be prefixed with an underscore: {', '.join(unexpected)}." + raise ValueError(msg) + + def to_json(self): + "Write to json dict." + res = {"doc_key": self.doc_key, "dataset": self.dataset} + sents_json = [sent.to_json() for sent in self] + fields_json = batches_to_fields(sents_json) + res.update(fields_json) + + if self.weight is not None: + res["weight"] = self.weight + + return res + + # TODO: Write a unit test to make sure this does the correct thing. + def split(self, max_tokens_per_doc): + """ + Greedily split a long document into smaller documents, each shorter than + `max_tokens_per_doc`. Each split document will get the same weight as its parent. + """ + # If the document is already short enough, return it as a list with a single item. + if self.n_tokens <= max_tokens_per_doc: + return [self] + + sentences = copy.deepcopy(self.sentences) + + sentence_groups = [] + current_group = [] + group_length = 0 + sentence_tok_offset = 0 + sentence_ix_offset = 0 + for sentence in sentences: + # Can't deal with single sentences longer than the limit. + if len(sentence) > max_tokens_per_doc: + msg = f"Sentence \"{''.join(sentence.text)}\" has more than {max_tokens_per_doc} tokens. Please split this sentence." + raise ValueError(msg) + + if group_length + len(sentence) <= max_tokens_per_doc: + # If we're not at the limit, add it to the current sentence group. + sentence.sentence_start -= sentence_tok_offset + sentence.sentence_ix -= sentence_ix_offset + current_group.append(sentence) + group_length += len(sentence) + else: + # Otherwise, start a new sentence group and adjust sentence offsets. + sentence_groups.append(current_group) + sentence_tok_offset = sentence.sentence_start + sentence_ix_offset = sentence.sentence_ix + sentence.sentence_start -= sentence_tok_offset + sentence.sentence_ix -= sentence_ix_offset + current_group = [sentence] + group_length = len(sentence) + + # Add the final sentence group. + sentence_groups.append(current_group) + + # Create a separate document for each sentence group. + doc_keys = [f"{self.doc_key}_SPLIT_{i}" for i in range(len(sentence_groups))] + res = [ + self.__class__( + doc_key, + self.dataset, + sentence_group, + self.weight, + ) + for doc_key, sentence_group in zip(doc_keys, sentence_groups) + ] + + return res + + def __repr__(self): + return "\n".join( + [ + str(i) + ": " + " ".join(sent.text) + for i, sent in enumerate(self.sentences) + ] + ) + + def __getitem__(self, ix): + return self.sentences[ix] + + def __len__(self): + return len(self.sentences) + + def print_plaintext(self): + for sent in self: + print(" ".join(sent.text)) + + @property + def n_tokens(self): + return sum([len(sent) for sent in self.sentences]) + + +class Sentence: + def __init__(self, entry, sentence_start, sentence_ix): + self.sentence_start = sentence_start + self.sentence_ix = sentence_ix + self.text = entry["sentences"] + + # Metadata fields are prefixed with a `_`. + self.metadata = {k: v for k, v in entry.items() if re.match("^_", k)} + + if "ner" in entry: + self.ner = [NER(this_ner, self) for this_ner in entry["ner"]] + self.ner_dict = {entry.span.span_sent: entry.label for entry in self.ner} + else: + self.ner = None + self.ner_dict = None + + # Predicted ner. + if "predicted_ner" in entry: + self.predicted_ner = [ + PredictedNER(this_ner, self) for this_ner in entry["predicted_ner"] + ] + else: + self.predicted_ner = None + + # Store relations. + if "relations" in entry: + self.relations = [ + Relation(this_relation, self) for this_relation in entry["relations"] + ] + relation_dict = {} + for rel in self.relations: + key = (rel.pair[0].span_sent, rel.pair[1].span_sent) + relation_dict[key] = rel.label + self.relation_dict = relation_dict + else: + self.relations = None + self.relation_dict = None + + # Predicted relations. + if "predicted_relations" in entry: + self.predicted_relations = [ + PredictedRelation(this_relation, self) + for this_relation in entry["predicted_relations"] + ] + else: + self.predicted_relations = None + + def to_json(self): + res = {"sentences": self.text} + if self.ner is not None: + res["ner"] = [entry.to_json() for entry in self.ner] + if self.predicted_ner is not None: + res["predicted_ner"] = [entry.to_json() for entry in self.predicted_ner] + if self.relations is not None: + res["relations"] = [entry.to_json() for entry in self.relations] + if self.predicted_relations is not None: + res["predicted_relations"] = [ + entry.to_json() for entry in self.predicted_relations + ] + + for k, v in self.metadata.items(): + res[k] = v + + return res + + def __repr__(self): + the_text = " ".join(self.text) + the_lengths = [len(x) for x in self.text] + tok_ixs = "" + for i, offset in enumerate(the_lengths): + true_offset = offset if i < 10 else offset - 1 + tok_ixs += str(i) + tok_ixs += " " * true_offset + + return the_text + "\n" + tok_ixs + + def __len__(self): + return len(self.text) + + +class Span: + def __init__(self, start, end, sentence, sentence_offsets=False): + # The `start` and `end` are relative to the document. We convert them to be relative to the + # sentence. + self.sentence = sentence + # Need to store the sentence text to make span objects hashable. + self.sentence_text = " ".join(sentence.text) + self.start_sent = start if sentence_offsets else start - sentence.sentence_start + self.end_sent = end if sentence_offsets else end - sentence.sentence_start + + @property + def start_doc(self): + return self.start_sent + self.sentence.sentence_start + + @property + def end_doc(self): + return self.end_sent + self.sentence.sentence_start + + @property + def span_doc(self): + return (self.start_doc, self.end_doc) + + @property + def span_sent(self): + return (self.start_sent, self.end_sent) + + @property + def text(self): + return self.sentence.text[self.start_sent : self.end_sent + 1] + + def __repr__(self): + return str((self.start_sent, self.end_sent, self.text)) + + def __eq__(self, other): + return ( + self.span_doc == other.span_doc + and self.span_sent == other.span_sent + and self.sentence == other.sentence + ) + + def __hash__(self): + tup = self.span_sent + (self.sentence_text,) + return hash(tup) + + +class Token: + def __init__(self, ix, sentence, sentence_offsets=False): + self.sentence = sentence + self.ix_sent = ix if sentence_offsets else ix - sentence.sentence_start + + @property + def ix_doc(self): + return self.ix_sent + self.sentence.sentence_start + + @property + def text(self): + return self.sentence.text[self.ix_sent] + + def __repr__(self): + return str((self.ix_sent, self.text)) + + +class NER: + def __init__(self, ner, sentence, sentence_offsets=False): + self.span = Span(ner[0], ner[1], sentence, sentence_offsets) + self.label = ner[2] + + def __repr__(self): + return f"{self.span.__repr__()}: {self.label}" + + def __eq__(self, other): + return self.span == other.span and self.label == other.label + + def to_json(self): + return list(self.span.span_doc) + [self.label] + + +class PredictedNER(NER): + def __init__(self, ner, sentence, sentence_offsets=False): + "The input should be a list: [span_start, span_end, label, raw_score, softmax_score]." + super().__init__(ner, sentence, sentence_offsets) + self.raw_score = ner[3] + self.softmax_score = ner[4] + + def __repr__(self): + return super().__repr__() + f" with confidence {self.softmax_score:0.4f}" + + def to_json(self): + return super().to_json() + [ + format_float(self.raw_score), + format_float(self.softmax_score), + ] + + +class Relation: + def __init__(self, relation, sentence, sentence_offsets=False): + start1, end1 = relation[0], relation[1] + start2, end2 = relation[2], relation[3] + label = relation[4] + span1 = Span(start1, end1, sentence, sentence_offsets) + span2 = Span(start2, end2, sentence, sentence_offsets) + self.pair = (span1, span2) + self.label = label + + def __repr__(self): + return f"{self.pair[0].__repr__()}, {self.pair[1].__repr__()}: {self.label}" + + def __eq__(self, other): + return (self.pair == other.pair) and (self.label == other.label) + + def to_json(self): + return list(self.pair[0].span_doc) + list(self.pair[1].span_doc) + [self.label] + + +class PredictedRelation(Relation): + def __init__(self, relation, sentence, sentence_offsets=False): + "Input format: [start_1, end_1, start_2, end_2, label, raw_score, softmax_score]." + super().__init__(relation, sentence, sentence_offsets) + self.raw_score = relation[5] + self.softmax_score = relation[6] + + def __repr__(self): + return super().__repr__() + f" with confidence {self.softmax_score:0.4f}" + + def to_json(self): + return super().to_json() + [ + format_float(self.raw_score), + format_float(self.softmax_score), + ] diff --git a/span_model/data/dataset_readers/span_model.py b/span_model/data/dataset_readers/span_model.py new file mode 100644 index 0000000..62366f2 --- /dev/null +++ b/span_model/data/dataset_readers/span_model.py @@ -0,0 +1,224 @@ +import json +import logging +import pickle as pkl +import warnings +from typing import Any, Dict + +from allennlp.common.file_utils import cached_path +from allennlp.data.dataset_readers.dataset_reader import DatasetReader +from allennlp.data.dataset_readers.dataset_utils import enumerate_spans +from allennlp.data.fields import ( + AdjacencyField, + LabelField, + ListField, + MetadataField, + SpanField, + TextField, +) +from allennlp.data.instance import Instance +from allennlp.data.token_indexers import SingleIdTokenIndexer, TokenIndexer +from allennlp.data.tokenizers import Token +from overrides import overrides + +from span_model.data.dataset_readers.document import Document, Sentence + +logger = logging.getLogger(__name__) # pylint: disable=invalid-name + + +class SpanModelDataException(Exception): + pass + + +@DatasetReader.register("span_model") +class SpanModelReader(DatasetReader): + """ + Reads a single JSON-formatted file. This is the same file format as used in the + scierc, but is preprocessed + """ + + def __init__( + self, + max_span_width: int, + token_indexers: Dict[str, TokenIndexer] = None, + **kwargs, + ) -> None: + super().__init__(**kwargs) + # New + self.is_train = False + + print("#" * 80) + + self._max_span_width = max_span_width + self._token_indexers = token_indexers or {"tokens": SingleIdTokenIndexer()} + + @overrides + def _read(self, file_path: str): + # if `file_path` is a URL, redirect to the cache + file_path = cached_path(file_path) + + with open(file_path, "r") as f: + lines = f.readlines() + + self.is_train = "train" in file_path # New + for line in lines: + # Loop over the documents. + doc_text = json.loads(line) + instance = self.text_to_instance(doc_text) + yield instance + + def _too_long(self, span): + return span[1] - span[0] + 1 > self._max_span_width + + def _process_ner(self, span_tuples, sent): + ner_labels = [""] * len(span_tuples) + + for span, label in sent.ner_dict.items(): + if self._too_long(span): + continue + # New + if span not in span_tuples: + continue + ix = span_tuples.index(span) + ner_labels[ix] = label + + return ner_labels + + def _process_relations(self, span_tuples, sent): + relations = [] + relation_indices = [] + + # Loop over the gold spans. Look up their indices in the list of span tuples and store + # values. + for (span1, span2), label in sent.relation_dict.items(): + # If either span is beyond the max span width, skip it. + if self._too_long(span1) or self._too_long(span2): + continue + # New + if (span1 not in span_tuples) or (span2 not in span_tuples): + continue + ix1 = span_tuples.index(span1) + ix2 = span_tuples.index(span2) + relation_indices.append((ix1, ix2)) + relations.append(label) + + return relations, relation_indices + + def _process_sentence(self, sent: Sentence, dataset: str): + # Get the sentence text and define the `text_field`. + sentence_text = [self._normalize_word(word) for word in sent.text] + text_field = TextField( + [Token(word) for word in sentence_text], self._token_indexers + ) + + # Enumerate spans. + spans = [] + for start, end in enumerate_spans( + sentence_text, max_span_width=self._max_span_width + ): + spans.append(SpanField(start, end, text_field)) + + # New + # spans = spans[:len(spans)//2] # bug: deliberately truncate + # labeled:Set[Tuple[int, int]] = set([span for span,label in sent.ner_dict.items()]) + # for span_pair, label in sent.relation_dict.items(): + # labeled.update(span_pair) + # existing:Set[Tuple[int, int]] = set([(s.span_start, s.span_end) for s in spans]) + # for start, end in labeled: + # if (start, end) not in existing: + # spans.append(SpanField(start, end, text_field)) + + span_field = ListField(spans) + span_tuples = [(span.span_start, span.span_end) for span in spans] + + # Convert data to fields. + # NOTE: The `ner_labels` and `coref_labels` would ideally have type + # `ListField[SequenceLabelField]`, where the sequence labels are over the `SpanField` of + # `spans`. But calling `as_tensor_dict()` fails on this specific data type. Matt G + # recognized that this is an AllenNLP API issue and suggested that represent these as + # `ListField[ListField[LabelField]]` instead. + fields = {} + fields["text"] = text_field + fields["spans"] = span_field + + if sent.ner is not None: + ner_labels = self._process_ner(span_tuples, sent) + fields["ner_labels"] = ListField( + [ + LabelField(entry, label_namespace=f"{dataset}__ner_labels") + for entry in ner_labels + ] + ) + if sent.relations is not None: + relation_labels, relation_indices = self._process_relations( + span_tuples, sent + ) + fields["relation_labels"] = AdjacencyField( + indices=relation_indices, + sequence_field=span_field, + labels=relation_labels, + label_namespace=f"{dataset}__relation_labels", + ) + + return fields + + def _process_sentence_fields(self, doc: Document): + # Process each sentence. + sentence_fields = [ + self._process_sentence(sent, doc.dataset) for sent in doc.sentences + ] + + # Make sure that all sentences have the same set of keys. + first_keys = set(sentence_fields[0].keys()) + for entry in sentence_fields: + if set(entry.keys()) != first_keys: + raise SpanModelDataException( + f"Keys do not match across sentences for document {doc.doc_key}." + ) + + # For each field, store the data from all sentences together in a ListField. + fields = {} + keys = sentence_fields[0].keys() + for key in keys: + this_field = ListField([sent[key] for sent in sentence_fields]) + fields[key] = this_field + + return fields + + @overrides + def text_to_instance(self, doc_text: Dict[str, Any]): + """ + Convert a Document object into an instance. + """ + doc = Document.from_json(doc_text) + + # Make sure there are no single-token sentences; these break things. + sent_lengths = [len(x) for x in doc.sentences] + if min(sent_lengths) < 2: + msg = ( + f"Document {doc.doc_key} has a sentence with a single token or no tokens. " + "This may break the modeling code." + ) + warnings.warn(msg) + + fields = self._process_sentence_fields(doc) + fields["metadata"] = MetadataField(doc) + + return Instance(fields) + + @overrides + def _instances_from_cache_file(self, cache_filename): + with open(cache_filename, "rb") as f: + for entry in pkl.load(f): + yield entry + + @overrides + def _instances_to_cache_file(self, cache_filename, instances): + with open(cache_filename, "wb") as f: + pkl.dump(instances, f, protocol=pkl.HIGHEST_PROTOCOL) + + @staticmethod + def _normalize_word(word): + if word == "/." or word == "/?": + return word[1:] + else: + return word diff --git a/span_model/predictors/__init__.py b/span_model/predictors/__init__.py new file mode 100644 index 0000000..2412584 --- /dev/null +++ b/span_model/predictors/__init__.py @@ -0,0 +1 @@ +from span_model.predictors.span_model import SpanModelPredictor diff --git a/span_model/predictors/span_model.py b/span_model/predictors/span_model.py new file mode 100644 index 0000000..d412c72 --- /dev/null +++ b/span_model/predictors/span_model.py @@ -0,0 +1,73 @@ +from typing import List +import numpy as np +import warnings + +from overrides import overrides +import numpy +import json + +from allennlp.common.util import JsonDict +from allennlp.nn import util +from allennlp.data import Batch +from allennlp.data import DatasetReader +from allennlp.models import Model +from allennlp.predictors.predictor import Predictor + + +@Predictor.register("span_model") +class SpanModelPredictor(Predictor): + """ + Predictor for SpanModel model. + + If model was trained on coref, prediction is done on a whole document at + once. This risks overflowing memory on large documents. + If the model was trained without coref, prediction is done by sentence. + """ + + def __init__(self, model: Model, dataset_reader: DatasetReader) -> None: + super().__init__(model, dataset_reader) + + def predict(self, document): + return self.predict_json({"document": document}) + + def predict_tokenized(self, tokenized_document: List[str]) -> JsonDict: + instance = self._words_list_to_instance(tokenized_document) + return self.predict_instance(instance) + + @overrides + def dump_line(self, outputs): + # Need to override to tell Python how to deal with Numpy ints. + return json.dumps(outputs, default=int) + "\n" + + # TODO: Can this be implemented in `forward_on_instance` instead? + @overrides + def predict_instance(self, instance): + """ + An instance is an entire document, represented as a list of sentences. + """ + model = self._model + cuda_device = model._get_prediction_device() + + # Try to predict this batch. + try: + dataset = Batch([instance]) + dataset.index_instances(model.vocab) + model_input = util.move_to_device(dataset.as_tensor_dict(), cuda_device) + prediction = model.make_output_human_readable( + model(**model_input) + ).to_json() + # If we run out of GPU memory, warn user and indicate that this document failed. + # This way, prediction doesn't grind to a halt every time we run out of GPU. + except RuntimeError as err: + # doc_key, dataset, sentences, message + metadata = instance["metadata"].metadata + doc_key = metadata.doc_key + msg = ( + f"Encountered a RunTimeError on document {doc_key}. Skipping this example." + f" Error message:\n{err.args[0]}." + ) + warnings.warn(msg) + prediction = metadata.to_json() + prediction["_FAILED_PREDICTION"] = True + + return prediction diff --git a/span_model/training/f1.py b/span_model/training/f1.py new file mode 100644 index 0000000..f1b8f49 --- /dev/null +++ b/span_model/training/f1.py @@ -0,0 +1,17 @@ +""" +Function to compute F1 scores. +""" + + +def safe_div(num, denom): + if denom > 0: + return num / denom + else: + return 0 + + +def compute_f1(predicted, gold, matched): + precision = safe_div(matched, predicted) + recall = safe_div(matched, gold) + f1 = safe_div(2 * precision * recall, precision + recall) + return precision, recall, f1 diff --git a/span_model/training/ner_metrics.py b/span_model/training/ner_metrics.py new file mode 100644 index 0000000..30178be --- /dev/null +++ b/span_model/training/ner_metrics.py @@ -0,0 +1,76 @@ +from overrides import overrides +from typing import Optional + +import torch + +from allennlp.training.metrics.metric import Metric + +from span_model.training.f1 import compute_f1 + +# TODO: Need to use the decoded predictions so that we catch the gold examples longer than +# the span boundary. + + +class NERMetrics(Metric): + """ + Computes precision, recall, and micro-averaged F1 from a list of predicted and gold labels. + """ + + def __init__(self, number_of_classes: int, none_label: int = 0): + self.number_of_classes = number_of_classes + self.none_label = none_label + self.reset() + + @overrides + def __call__( + self, + predictions: torch.Tensor, + gold_labels: torch.Tensor, + mask: Optional[torch.Tensor] = None, + ): + predictions = predictions.cpu() + gold_labels = gold_labels.cpu() + mask = mask.cpu() + for i in range(self.number_of_classes): + if i == self.none_label: + continue + self._true_positives += ( + ((predictions == i) * (gold_labels == i) * mask.bool()).sum().item() + ) + self._false_positives += ( + ((predictions == i) * (gold_labels != i) * mask.bool()).sum().item() + ) + self._true_negatives += ( + ((predictions != i) * (gold_labels != i) * mask.bool()).sum().item() + ) + self._false_negatives += ( + ((predictions != i) * (gold_labels == i) * mask.bool()).sum().item() + ) + + @overrides + def get_metric(self, reset=False): + """ + Returns + ------- + A tuple of the following metrics based on the accumulated count statistics: + precision : float + recall : float + f1-measure : float + """ + predicted = self._true_positives + self._false_positives + gold = self._true_positives + self._false_negatives + matched = self._true_positives + precision, recall, f1_measure = compute_f1(predicted, gold, matched) + + # Reset counts if at end of epoch. + if reset: + self.reset() + + return precision, recall, f1_measure + + @overrides + def reset(self): + self._true_positives = 0 + self._false_positives = 0 + self._true_negatives = 0 + self._false_negatives = 0 diff --git a/span_model/training/relation_metrics.py b/span_model/training/relation_metrics.py new file mode 100644 index 0000000..a4f2301 --- /dev/null +++ b/span_model/training/relation_metrics.py @@ -0,0 +1,63 @@ +from overrides import overrides + +from allennlp.training.metrics.metric import Metric + +from span_model.training.f1 import compute_f1 + + +class RelationMetrics(Metric): + """ + Computes precision, recall, and micro-averaged F1 from a list of predicted and gold spans. + """ + + def __init__(self): + self.reset() + + # TODO: This requires decoding because the dataset reader gets rid of gold spans wider + # than the span width. So, I can't just compare the tensor of gold labels to the tensor of + # predicted labels. + @overrides + def __call__(self, predicted_relation_list, metadata_list): + for predicted_relations, metadata in zip( + predicted_relation_list, metadata_list + ): + gold_relations = metadata.relation_dict + self._total_gold += len(gold_relations) + self._total_predicted += len(predicted_relations) + for (span_1, span_2), label in predicted_relations.items(): + ix = (span_1, span_2) + if ix in gold_relations and gold_relations[ix] == label: + self._total_matched += 1 + + @overrides + def get_metric(self, reset=False): + precision, recall, f1 = compute_f1( + self._total_predicted, self._total_gold, self._total_matched + ) + + # Reset counts if at end of epoch. + if reset: + self.reset() + + return precision, recall, f1 + + @overrides + def reset(self): + self._total_gold = 0 + self._total_predicted = 0 + self._total_matched = 0 + + +class SpanPairMetrics(RelationMetrics): + @overrides + def __call__(self, predicted_relation_list, metadata_list): + for predicted_relations, metadata in zip( + predicted_relation_list, metadata_list + ): + gold_relations = metadata.relation_dict + self._total_gold += len(gold_relations) + self._total_predicted += len(predicted_relations) + for (span_1, span_2), label in predicted_relations.items(): + ix = (span_1, span_2) + if ix in gold_relations: + self._total_matched += 1 diff --git a/train.py b/train.py new file mode 100644 index 0000000..48c965e --- /dev/null +++ b/train.py @@ -0,0 +1,39 @@ +# @title Data Exploration + +import sys +import torch +import json +from pathlib import Path +from aste.data_utils import Data, Sentence, SplitEnum +from aste.wrapper import SpanModel +import argparse + +# 解析参数 +parser = argparse.ArgumentParser(description="Train the model.") +parser.add_argument('--random_seed', type=int, required=True, help='Random seed') +parser.add_argument('--model_name', type=str, required=True, help='Model name') +args = parser.parse_args() + +random_seed = args.random_seed +data_name = args.model_name # 所用的数据集名称,也是outputs目录中保存的模型文件夹名称 + +assert torch.cuda.is_available() + +sys.path.append("") +path = f"aste/data/triplet_data/{data_name}/train.txt" +data = Data.load_from_full_path(path) + +template = "https://github.com/chiayewken/Span-ASTE/releases/download/v1.0.0/{}.tar" +url = template.format(data_name) +model_tar = Path(url).name +model_dir = Path(url).stem + + +path_train = f"aste/data/triplet_data/{data_name}/train.txt" +path_dev = f"aste/data/triplet_data/{data_name}/dev.txt" +save_dir = f"outputs/{data_name}/seed_{random_seed}" + +model = SpanModel(save_dir=save_dir, random_seed=random_seed) +model.fit(path_train, path_dev) + +print("####################################") \ No newline at end of file diff --git a/training_config/config.json b/training_config/config.json new file mode 100644 index 0000000..fd2b08b --- /dev/null +++ b/training_config/config.json @@ -0,0 +1,121 @@ +{ + "data_loader": { + "sampler": { + "type": "random" + } + }, + "dataset_reader": { + "max_span_width": 8, + "token_indexers": { + "bert": { + "max_length": 512, + "model_name": "./span_model/models/bert", + "type": "pretrained_transformer_mismatched" + } + }, + "type": "span_model" + }, + "model": { + "embedder": { + "token_embedders": { + "bert": { + "max_length": 512, + "model_name": "./span_model/models/bert", + "type": "pretrained_transformer_mismatched" + } + } + }, + "feature_size": 20, + "feedforward_params": { + "dropout": 0.40000000000000002, + "hidden_dims": 150, + "num_layers": 2 + }, + "initializer": { + "regexes": [ + [ + "_span_width_embedding.weight", + { + "type": "xavier_normal" + } + ] + ] + }, + "loss_weights": { + "ner": 1, + "relation": 1 + }, + "max_span_width": 8, + "module_initializer": { + "regexes": [ + [ + ".*weight", + { + "type": "xavier_normal" + } + ], + [ + ".*weight_matrix", + { + "type": "xavier_normal" + } + ] + ] + }, + "modules": { + "ner": { }, + "relation": { + "spans_per_word": 0.5, + "use_distance_embeds": true, + "use_pruning": true + } + }, + "span_extractor_type": "endpoint", + "target_task": "relation", + "type": "span_model", + "use_span_width_embeds": true + }, + "numpy_seed": 0, + "pytorch_seed": 0, + "random_seed": 0, + "test_data_path": "", + "train_data_path": "", + "trainer": { + "checkpointer": { + "num_serialized_models_to_keep": 1 + }, + "cuda_device": 0, + "grad_norm": 5, + "learning_rate_scheduler": { + "type": "slanted_triangular" + }, + "num_epochs": 2, + "optimizer": { + "lr": 0.001, + "parameter_groups": [ + [ + [ + "_matched_embedder" + ], + { + "finetune": true, + "lr": 5.0000000000000002e-05, + "weight_decay": 0.01 + } + ], + [ + [ + "scalar_parameters" + ], + { + "lr": 0.01 + } + ] + ], + "type": "adamw", + "weight_decay": 0 + }, + "validation_metric": "+MEAN__relation_f1" + }, + "validation_data_path": "" +}