fasttext: есть ли способ экспорта нграмм? - PullRequest
0 голосов
/ 12 марта 2019

Я новичок в DL и NLP, и недавно начал использовать предварительно обученную модель внедрения fastText (cc.en.300.bin) через gensim.

Я хотел бы иметь возможность вычислять векторы для слов из словарного запаса самостоятельно, разбивая слово на n-граммы и просматривая вектор для каждого n-грамма.

Я не смог найти способ экспортировать n-граммовые векторы, которые являются частью модели. Я понимаю, что они хэшированы, но, возможно, есть способ (не обязательно с помощью gensim) получить их?

Любое понимание будет оценено!

Ответы [ 2 ]

0 голосов
/ 12 мая 2019

Недавно я сам столкнулся с этой проблемой, и мне пришлось написать скрипт, чтобы уменьшить размер модели. Код Fasttext C включает в себя удобную функцию «порог» для уменьшения размера словаря, но он не подвержен привязкам Python. После сокращения словаря вам также необходимо перестроить входную матрицу, включая блоки ngram, которые идут после векторов основного слова. После сохранения модели таким образом все векторы слов будут генерироваться только из информации подслов (кроме словарных слов, которые остаются)

для поиска сходства слов, output_ и model_ не используются. Чтобы сохранить больше памяти, вы также можете просто закомментировать часть, которая записывает output_ в saveModel

обратите внимание, что записи ngram сами по себе составляют около 2 Гб в английской предварительно обученной модели, так что это самая маленькая модель, которую вы можете создать, даже если все словарные слова удалены.

/* note: some dict_ members are public for easier access */
void FastText::quantize(const Args& qargs) {
  /*if (args_->model != model_name::sup) {
    throw std::invalid_argument(
        "For now we only support quantization of supervised models");
  }*/
  args_->input = qargs.input;
  args_->qout = qargs.qout;
  args_->output = qargs.output;
  std::shared_ptr<DenseMatrix> input =
      std::dynamic_pointer_cast<DenseMatrix>(input_);
  std::shared_ptr<DenseMatrix> output =
      std::dynamic_pointer_cast<DenseMatrix>(output_);
  bool normalizeGradient = (args_->model == model_name::sup);

  if (qargs.cutoff > 0 && qargs.cutoff < input->size(0)) {
    /*auto idx = selectEmbeddings(qargs.cutoff);
    dict_->prune(idx);*/
    int32_t rows = dict_->size_+args_->bucket;
    dict_->threshold(2000, 2000);
    std::cerr << "words:  " << dict_->size_ << std::endl;
    std::cerr << "rows:  " << rows << std::endl;
    /*std::shared_ptr<DenseMatrix> ninput =
        std::make_shared<DenseMatrix>(idx.size(), args_->dim);*/
    int32_t new_rows = dict_->size_+args_->bucket;
    std::shared_ptr<DenseMatrix> ninput = std::make_shared<DenseMatrix>(dict_->size_+args_->bucket, args_->dim);
    for (auto i = 0; i < dict_->size_; i++) {
      for (auto j = 0; j < args_->dim; j++) {
        int32_t index = dict_->getId(dict_->words_[i].word);
        ninput->at(i, j) = input->at(index, j);
      }
    }

    int32_t offset = rows-new_rows;
    for (auto i = dict_->size_; i < new_rows; i++) {
      for (auto j = 0; j < args_->dim; j++) {
        ninput->at(i, j) = input->at(i+offset, j);
      }
    }
    /*input = ninput;*/
    input_ = ninput;
    if (qargs.retrain) {
      args_->epoch = qargs.epoch;
      args_->lr = qargs.lr;
      args_->thread = qargs.thread;
      args_->verbose = qargs.verbose;
      auto loss = createLoss(output_);
      model_ = std::make_shared<Model>(input, output, loss, normalizeGradient);
      startThreads();
    }
  }

  /*input_ = std::make_shared<QuantMatrix>(
      std::move(*(input.get())), qargs.dsub, qargs.qnorm);*/

  /*if (args_->qout) {
    output_ = std::make_shared<QuantMatrix>(
        std::move(*(output.get())), 2, qargs.qnorm);
  }
*/
  /*quant_ = true;*/
  auto loss = createLoss(output_);
  model_ = std::make_shared<Model>(input_, output_, loss, normalizeGradient);
}
0 голосов
/ 12 марта 2019

Вы можете точно посмотреть, как код gensim создает векторы слов FastText для слов из словарного запаса, непосредственно проверив его исходный код для метода FastTextKeyedVectors class word_vec():

https://github.com/RaRe-Technologies/gensim/blob/3aeee4dc460be84ee4831bf55ca4320757c72e7b/gensim/models/keyedvectors.py#L2069

(Обратите внимание, что этот исходный код в ветке gensim develop может отражать последние исправления FastText, которые не будут соответствовать тому, что установлен в вашем пакете до gensim версии 3.7.1; вы можете обратиться к установите локальный исходный код пакета или дождитесь официального выпуска этих исправлений.)

Поскольку Python не защищает какую-либо часть соответствующих объектов от внешнего доступа (с помощью таких вещей, как принудительные «частные» обозначения), вы можете выполнять те же самые операции извне класса.

Обратите особое внимание, что в текущем коде (который соответствует поведению исходной реализации Facebook) векторы n-грамм будут извлечены из сегментов структуры хэш-таблицы ngram_weights независимо от того, были ли ваши текущие n-граммы действительно известны в тренировочных данных или нет. В тех случаях, когда эти n-граммы были известны и значимы в обучающих данных, это должно немного помочь в векторе OOV. В тех случаях, когда вместо него получается произвольный другой вектор, такая случайность не должна сильно навредить.

...