AllenNLP DatasetReader.read returns 生成器而不是 AllennlpDataset
AllenNLP DatasetReader.read returns generator instead of AllennlpDataset
在研究 AllenNLP 框架(版本 2.0.1)时,我尝试实现来自 https://guide.allennlp.org/training-and-prediction#1.
的示例代码
从 Parquet 文件读取数据时,我得到:
TypeError: unsupported operand type(s) for +: 'generator' and 'generator'
下一行:
vocab = build_vocab(train_data + dev_data)
我怀疑 return 值应该是 AllennlpDataset 但也许我把它搞混了。
我做错了什么?
完整代码:
train_path = <some_path>
test_path = <some_other_path>
class ClassificationJobReader(DatasetReader):
def __init__(self,
lazy: bool = False,
tokenizer: Tokenizer = None,
token_indexers: Dict[str, TokenIndexer] = None,
max_tokens: int = None):
super().__init__(lazy)
self.tokenizer = tokenizer or WhitespaceTokenizer()
self.token_indexers = token_indexers or {'tokens': SingleIdTokenIndexer()}
self.max_tokens = max_tokens
def _read(self, file_path: str) -> Iterable[Instance]:
df = pd.read_parquet(data_path)
for idx in df.index:
text = row['title'][idx] + ' ' + row['description'][idx]
print(f'text : {text}')
label = row['class_id'][idx]
print(f'label : {label}')
tokens = self.tokenizer.tokenize(text)
if self.max_tokens:
tokens = tokens[:self.max_tokens]
text_field = TextField(tokens, self.token_indexers)
label_field = LabelField(label)
fields = {'text': text_field, 'label': label_field}
yield Instance(fields)
def build_dataset_reader() -> DatasetReader:
return ClassificationJobReader()
def read_data(reader: DatasetReader) -> Tuple[Iterable[Instance], Iterable[Instance]]:
print("Reading data")
training_data = reader.read(train_path)
validation_data = reader.read(test_path)
return training_data, validation_data
def build_vocab(instances: Iterable[Instance]) -> Vocabulary:
print("Building the vocabulary")
return Vocabulary.from_instances(instances)
dataset_reader = build_dataset_reader()
train_data, dev_data = read_data(dataset_reader)
vocab = build_vocab(train_data + dev_data)
感谢您的帮助
请先在下面找到代码修复,然后再找到解释。
代码修复
# the extend_from_instances expands your vocabulary with the instances passed as an arg
# and is therefore equivalent to Vocabulary.from_instances(train_data + dev_data)
# previously
vocabulary.extend_from_instances(train_data)
vocabulary.extend_from_instances(dev_data)
说明
这是因为 AllenNLP API 在 allennlp==2.0.1 中进行了一些重大更改。您可以找到变更日志 here and the upgrade guide here。根据我的理解,该指南已过时(它反映了 allennlp<=1.4)。
DatasetReader return现在是生成器,而不是以前的列表。 DatasetReader 曾经有一个名为“lazy”的参数,用于延迟加载数据。默认情况下为 False,因此 dataset_reader.read
之前会 return 一个列表。但是,从 v2.0 开始(如果我没记错的话),默认情况下会应用延迟加载,因此默认情况下 return 是一个生成器。如您所知,“+”运算符尚未被生成器对象覆盖,因此您不能简单地添加两个生成器。
因此,您可以简单地使用 vocab.extend_from_instances
来实现与以前相同的行为。希望这对你有帮助。如果您需要完整的代码片段,请在下面发表评论,我可以 post 重新整理要点并与您分享。
美好的一天!
在研究 AllenNLP 框架(版本 2.0.1)时,我尝试实现来自 https://guide.allennlp.org/training-and-prediction#1.
的示例代码 从 Parquet 文件读取数据时,我得到:
TypeError: unsupported operand type(s) for +: 'generator' and 'generator'
下一行:
vocab = build_vocab(train_data + dev_data)
我怀疑 return 值应该是 AllennlpDataset 但也许我把它搞混了。 我做错了什么?
完整代码:
train_path = <some_path>
test_path = <some_other_path>
class ClassificationJobReader(DatasetReader):
def __init__(self,
lazy: bool = False,
tokenizer: Tokenizer = None,
token_indexers: Dict[str, TokenIndexer] = None,
max_tokens: int = None):
super().__init__(lazy)
self.tokenizer = tokenizer or WhitespaceTokenizer()
self.token_indexers = token_indexers or {'tokens': SingleIdTokenIndexer()}
self.max_tokens = max_tokens
def _read(self, file_path: str) -> Iterable[Instance]:
df = pd.read_parquet(data_path)
for idx in df.index:
text = row['title'][idx] + ' ' + row['description'][idx]
print(f'text : {text}')
label = row['class_id'][idx]
print(f'label : {label}')
tokens = self.tokenizer.tokenize(text)
if self.max_tokens:
tokens = tokens[:self.max_tokens]
text_field = TextField(tokens, self.token_indexers)
label_field = LabelField(label)
fields = {'text': text_field, 'label': label_field}
yield Instance(fields)
def build_dataset_reader() -> DatasetReader:
return ClassificationJobReader()
def read_data(reader: DatasetReader) -> Tuple[Iterable[Instance], Iterable[Instance]]:
print("Reading data")
training_data = reader.read(train_path)
validation_data = reader.read(test_path)
return training_data, validation_data
def build_vocab(instances: Iterable[Instance]) -> Vocabulary:
print("Building the vocabulary")
return Vocabulary.from_instances(instances)
dataset_reader = build_dataset_reader()
train_data, dev_data = read_data(dataset_reader)
vocab = build_vocab(train_data + dev_data)
感谢您的帮助
请先在下面找到代码修复,然后再找到解释。
代码修复
# the extend_from_instances expands your vocabulary with the instances passed as an arg
# and is therefore equivalent to Vocabulary.from_instances(train_data + dev_data)
# previously
vocabulary.extend_from_instances(train_data)
vocabulary.extend_from_instances(dev_data)
说明
这是因为 AllenNLP API 在 allennlp==2.0.1 中进行了一些重大更改。您可以找到变更日志 here and the upgrade guide here。根据我的理解,该指南已过时(它反映了 allennlp<=1.4)。
DatasetReader return现在是生成器,而不是以前的列表。 DatasetReader 曾经有一个名为“lazy”的参数,用于延迟加载数据。默认情况下为 False,因此 dataset_reader.read
之前会 return 一个列表。但是,从 v2.0 开始(如果我没记错的话),默认情况下会应用延迟加载,因此默认情况下 return 是一个生成器。如您所知,“+”运算符尚未被生成器对象覆盖,因此您不能简单地添加两个生成器。
因此,您可以简单地使用 vocab.extend_from_instances
来实现与以前相同的行为。希望这对你有帮助。如果您需要完整的代码片段,请在下面发表评论,我可以 post 重新整理要点并与您分享。
美好的一天!