webentwicklung-frage-antwort-db.com.de

Konvertieren Sie die Word2vec-Bin-Datei in Text

Ich kann GoogleNews-Vectors-negative300.bin.gz von der Word2vec - Site herunterladen. Die .bin-Datei (etwa 3,4 GB) ist ein binäres Format, das für mich nicht nützlich ist. Tomas Mikolov versichert uns dass "Es sollte ziemlich einfach sein, das Binärformat in ein Textformat zu konvertieren (obwohl dies mehr Speicherplatz benötigt). Überprüfen Sie den Code im Entfernungswerkzeug. " Leider verstehe ich nicht genügend C, um http://Word2vec.googlecode.com/svn/trunk/distance.c zu verstehen.

Angeblich kann gensim dies auch tun, aber bei allen Tutorials, die ich gefunden habe, scheint es sich um das Konvertieren von aus - Text zu handeln, nicht umgekehrt.

Kann jemand Änderungen am C-Code oder Anweisungen für gensim zum Ausgeben von Text vorschlagen?

54
Glenn

In der Word2vec-Toolkit-Mailingliste hat Thomas Mensink eine answer in Form eines kleinen C-Programms bereitgestellt, das eine .bin-Datei in Text konvertiert. Dies ist eine Modifikation der Datei distance.c. Ich ersetzte die ursprüngliche distance.c durch den folgenden Code von Thomas und baute Word2vec neu (make clean; make) und benannte die kompilierte Distanz in readbin um. Dann erstellt ./readbin vector.bin eine Textversion von vector.bin.

//  Copyright 2013 Google Inc. All Rights Reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.Apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <malloc.h>

const long long max_size = 2000;         // max length of strings
const long long N = 40;                  // number of closest words that will be shown
const long long max_w = 50;              // max length of vocabulary entries

int main(int argc, char **argv) {
  FILE *f;
  char file_name[max_size];
  float len;
  long long words, size, a, b;
  char ch;
  float *M;
  char *vocab;
  if (argc < 2) {
    printf("Usage: ./distance <FILE>\nwhere FILE contains Word projections in the BINARY FORMAT\n");
    return 0;
  }
  strcpy(file_name, argv[1]);
  f = fopen(file_name, "rb");
  if (f == NULL) {
    printf("Input file not found\n");
    return -1;
  }
  fscanf(f, "%lld", &words);
  fscanf(f, "%lld", &size);
  vocab = (char *)malloc((long long)words * max_w * sizeof(char));
  M = (float *)malloc((long long)words * (long long)size * sizeof(float));
  if (M == NULL) {
    printf("Cannot allocate memory: %lld MB    %lld  %lld\n", (long long)words * size * sizeof(float) / 1048576, words, size);
    return -1;
  }
  for (b = 0; b < words; b++) {
    fscanf(f, "%s%c", &vocab[b * max_w], &ch);
    for (a = 0; a < size; a++) fread(&M[a + b * size], sizeof(float), 1, f);
    len = 0;
    for (a = 0; a < size; a++) len += M[a + b * size] * M[a + b * size];
    len = sqrt(len);
    for (a = 0; a < size; a++) M[a + b * size] /= len;
  }
  fclose(f);
  //Code added by Thomas Mensink
  //output the vectors of the binary format in text
  printf("%lld %lld #File: %s\n",words,size,file_name);
  for (a = 0; a < words; a++){
    printf("%s ",&vocab[a * max_w]);
    for (b = 0; b< size; b++){ printf("%f ",M[a*size + b]); }
    printf("\b\b\n");
  }  

  return 0;
}

Ich habe das "\ b\b" aus der printf entfernt. 

Übrigens enthielt die resultierende Textdatei immer noch das Textwort Word und einige unnötige Leerzeichen, die ich für einige numerische Berechnungen nicht wollte. Mit Bash-Befehlen entfernte ich die erste Textspalte und das nachfolgende Leerzeichen aus jeder Zeile.

cut --complement -d ' ' -f 1 GoogleNews-vectors-negative300.txt > GoogleNews-vectors-negative300_tuples-only.txt
sed 's/ $//' GoogleNews-vectors-negative300_tuples-only.txt
17
Glenn

Ich benutze diesen Code, um das binäre Modell zu laden, und speichere es dann in einer Textdatei. 

from gensim.models.keyedvectors import KeyedVectors

model = KeyedVectors.load_Word2vec_format('path/to/GoogleNews-vectors-negative300.bin', binary=True)
model.save_Word2vec_format('path/to/GoogleNews-vectors-negative300.txt', binary=False)

Referenzen: API und nullege

Hinweis: 

Der obige Code ist für die new -Version von gensim. Für die vorherige -Version habe ich diesen Code verwendet.

from gensim.models import Word2vec

model = Word2vec.Word2Vec.load_Word2vec_format('path/to/GoogleNews-vectors-negative300.bin', binary=True)
model.save_Word2vec_format('path/to/GoogleNews-vectors-negative300.txt', binary=False)
66
silo

das Format ist ein IEEE 754-Binär-Gleitkommaformat mit einfacher Genauigkeit: binary32 http://en.wikipedia.org/wiki/Single-precision_floating-point_format Sie verwenden Little-Endian.

Lassen Sie uns ein Beispiel machen:

  • Die erste Zeile ist das String-Format: "3000000 300\n" (vocabSize & VecSize, getByte bis Byte == '\ n') 
  • Die nächste Zeile enthält zuerst das Vokab Word und dann (300 * 4 Byte Float-Wert, 4 Byte für jede Dimension):

    getByte till byte==32 (space). (60 47 115 62 32 => <\s>[space])
    
  • dann repräsentiert jedes 4 Byte eine Float-Nummer

    nächstes 4 Byte: 0 0 bis 108 58 => 0,001129150390625.

Sie können den Wikipedia-Link überprüfen, um zu sehen, wie, lassen Sie mich dies als Beispiel tun:

(Little-Endian -> umgekehrte Reihenfolge) 00111010 10010100 00000000 00000000

  • erstes ist Vorzeichenbit => Zeichen = 1 (sonst = -1)
  • nächste 8 Bits => 117 => exp = 2 ^ (117-127) 
  • nächste 23 Bits => pre = 0 * 2 ^ (- 1) + 0 * 2 ^ (- 2) + 1 * 2 ^ (- 3) + 1 * 2 ^ (- 5)

value = sign * exp * pre

7
dbao50

Sie können die Binärdatei in Word2vec laden und die Textversion dann wie folgt speichern: 

from gensim.models import Word2vec
 model = Word2vec.Word2Vec.load_Word2vec_format('Path/to/GoogleNews-vectors-negative300.bin', binary=True)
 model.save("file.txt")

`

5
batgirl

Ich verwende gensim, um mit GoogleNews-Vectors-negative300.bin zu arbeiten, und füge beim Laden des Modells ein binary = True-Flag hinzu.

from gensim import Word2vec

model = Word2vec.Word2Vec.load_Word2vec_format('Path/to/GoogleNews-vectors-negative300.bin', binary=True) 

Scheint gut zu funktionieren.

4
zaytsev

Ich hatte ein ähnliches Problem, ich wollte bin/non-bin (gensim) Modelle als CSV ausgeben.

hier ist der Code, der das auf Python macht, es setzt voraus, dass Sie gensim installiert haben:

https://Gist.github.com/dav009/10a742de43246210f3ba

2
David Przybilla

convertvec ist ein kleines Tool zum Konvertieren von Vektoren zwischen verschiedenen Formaten für die Word2vec-Bibliothek.

Vektoren von binärem in einfachen Text konvertieren:

./convertvec bin2txt input.bin output.txt

Vektoren vom Klartext in den Binärcode konvertieren:

./convertvec txt2bin input.txt output.bin

2
Hamed Ganji

Wenn Sie den Fehler erhalten:

ImportError: No module named models.Word2vec

dann, weil es ein API-Update gab. Das wird funktionieren:

from gensim.models.keyedvectors import KeyedVectors

model = KeyedVectors.load_Word2vec_format('./GoogleNews-vectors-negative300.bin', binary=True)
model.save_Word2vec_format('./GoogleNews-vectors-negative300.txt', binary=False)
1

Hier ist der Code, den ich verwende:

import codecs
from gensim.models import Word2Vec

def main():
    path_to_model = 'GoogleNews-vectors-negative300.bin'
    output_file = 'GoogleNews-vectors-negative300_test.txt'
    export_to_file(path_to_model, output_file)


def export_to_file(path_to_model, output_file):
    output = codecs.open(output_file, 'w' , 'utf-8')
    model = Word2Vec.load_Word2vec_format(path_to_model, binary=True)
    print('done loading Word2Vec')
    vocab = model.vocab
    for mid in vocab:
        #print(model[mid])
        #print(mid)
        vector = list()
        for dimension in model[mid]:
            vector.append(str(dimension))
        #line = { "mid": mid, "vector": vector  }
        vector_str = ",".join(vector)
        line = mid + "\t"  + vector_str
        #line = json.dumps(line)
        output.write(line + "\n")
    output.close()

if __== "__main__":
    main()
    #cProfile.run('main()') # if you want to do some profiling
1

Nur ein kurzes Update, da es jetzt einfacher geht.

Wenn Sie Word2vec aus https://github.com/dav/Word2vec verwenden, gibt es eine zusätzliche Option namens -binary, die 1 zur Erzeugung einer Binärdatei oder 0 zur Erstellung einer Textdatei akzeptiert. Dieses Beispiel stammt aus demo-Word.sh im Repo:

time ./Word2vec -train text8 -output vectors.bin -cbow 1 -size 200 -window 8 -negative 25 -hs 0 -sample 1e-4 -threads 20 -binary 0 -iter 15

0
Yohanes Gultom