

word2vecというC言語のプログラムで単語情報を多次元ベクトル化する際に出力されたテキストファイルが手元にあります。
次のコードの`else`の文章で出力されたものです。

[code]

    for (a = 0; a < vocab_size; a++) {
        fprintf(fo, "%s ", vocab[a].word);
        if (binary) for (b = 0; b < layer1_size; b++) fwrite(&syn0[a * layer1_size + b], sizeof(real), 1, fo);
        else for (b = 0; b < layer1_size; b++) fprintf(fo, "%lf ", syn0[a * layer1_size + b]);
        fprintf(fo, "\n");
    } 
    
[/code]

[ソース](https://code.google.com/p/word2vec/source/browse/trunk/word2vec.c?r=41#562)

`if(binary)`の`else`の方で出力されたベクトルファイルが手元にありますが、その後`if(binary)`の方で出力されたファイルが必要になりました。
ファイルの中身は以下のようになっています。

<単語><スペース><数値><スペース><数値><スペース>

今書いているコードは次のようです。

* * *
[code]

    # -*- coding: utf-8 -*-
    import sys
    import struct
    #テキストベクトルデータの読み込み
    title = sys.argv[1:]
    i = 0
    fp = open('binaryVec.bin','wb')
    odata = ''
    
    for line in open(title[0]):
        chars = list(map(hex, map(ord, line)))
        print line
        print chars
        odata += struct.pack('s',chars)
    fp.write(odata)
    fp.close()
    
[/code]

* * *

データが大きいため効率のよい変換プログラムがあると良いです。

よろしくお願いします。

文字コードはテキストもpythonプログラムもutf-8を使用しています。 テキストベクトルの一部を載せます。

* * *
[code]

    多い 0.205392 -0.245325 0.240983 0.533283 0.087030 -0.198588 0.395930 0.331363 -0.212541 0.383991 0.391010 0.140275 0.178444 -0.331018 -0.303288 -0.168199 0.227571 -0.133808 -0.583108 -0.004697 -0.068092 -0.057790 0.199027 -0.443492 0.006436 -0.098054 0.221261 -0.413350 -0.274608 -0.266688 0.198686 -0.347939 -0.272542 -0.005835 0.195161 0.255993 -0.435598 0.083113 -0.061061 -0.602378 0.244479 -0.090220 0.053294 0.225144 0.084010 0.150409 -0.078552 0.184509 0.068329 -0.045706 -0.037543 -0.347720 0.363027 -0.251563 -0.293957 0.201196 -0.062295 -0.102561 -0.093551 -0.212615 -0.000832 -0.071720 -0.404002 0.124075 0.283026 0.108321 -0.177551 -0.681601 0.051641 0.324483 0.078215 -0.282532 0.313095 -0.250052 -0.872598 0.035464 -0.266010 -0.389549 -0.120772 0.243341 -0.255850 0.044791 -0.151454 0.159697 -0.320580 -0.663053 0.167484 0.361221 0.185417 0.342295 0.889678 -0.302563 0.289107 -0.102576 0.263508 -0.012531 0.298031 -0.515175 -0.127688 -0.260832 
    可能 0.108951 -0.258674 0.629972 0.311664 -0.077146 -0.124886 -0.096122 0.011065 -0.309206 0.867305 0.633274 0.006818 0.267469 -0.119733 0.521135 -0.064882 -0.018288 -0.010180 -0.729432 -0.028794 -0.299309 -0.141295 0.623287 -0.417451 0.007524 0.092700 0.215297 -0.506577 -0.271396 -0.184997 -0.198890 -0.349385 -0.178141 0.230034 0.141386 0.193577 0.223477 0.341060 -0.165425 -0.397568 0.020117 0.154478 0.313013 0.013119 0.172535 0.277345 -0.347708 0.686350 -0.181311 0.344334 -0.119619 -0.433781 0.426598 -0.588145 -0.155892 0.060375 0.023153 0.062405 0.193624 -0.262037 0.259582 0.140148 -0.697635 -0.071356 0.526129 -0.122136 -0.622095 -0.284502 0.130523 0.427264 0.295688 -0.340023 0.310286 -0.043206 -0.201572 -0.319277 0.377619 0.101276 -0.208789 0.099027 0.056171 -0.081605 -0.523134 0.181316 -0.018701 -0.517925 -0.108934 0.514148 0.504512 0.430822 0.481150 -0.165199 0.472695 0.080885 -0.141376 0.324130 0.128912 -0.219854 -0.160605 -0.224664 
    
[/code]


CC BY-SA 3.0
2014-12-14T05:02:03.937
1589
2014-12-15T10:51:33.197
2014-12-15T10:51:33.197
2155
2155
question
python c word2vec 自然言語処理
word2vecでテキストモードで出力した結果を、binaryモードでの出力結果にPythonで変換したい


**前半部分** 質問も大分体裁が変わったので前半は削除しました。

* * *

# 日本語出力部分について追記

文字コードが不明なのでそこは気がかりですが、以下の様にすれば出力できると思います。  
ライブラリの利用は @ywat
さんが[こちらで](https://ja.stackoverflow.com/a/1591/728)示しておられるので、私はベタな形で。

[code]

    import struct
    
    def write(out_filename, word, float_strings):
        with open(out_filename, "ab") as fp:
            fp.write(word)
            fp.write(struct.pack('b',0x20))
            for x in float_strings:
                fp.write(struct.pack('f', float(x)))
            fp.write(struct.pack('b',0x0a))
    
    def convert(from_filename, to_filename):
        with open(from_filename, "rt") as f:
            with open(to_filename, "wb") as fp:
                # to empty
                pass
    
            for line in f:
                splited=line.split(" ")
                write(to_filename, splited[0], splited[1:])
    
    
    if __name__=='__main__':
        convert('sampleIn.txt', 'binaryVec.bin')
    
[/code]

sampleIn.txtは以下の様なテキストです。

[code]

    データ 1.1 2.2
    データ2 1.1 2.2
    
[/code]

SJISですと以下の様なバイナリになります。  
![画像の説明をここに入力](https://i.stack.imgur.com/5PUbK.jpg)


CC BY-SA 3.0
2014-12-14T05:39:17.823
1590
2014-12-14T07:46:00.517
2017-04-13T12:52:38.920
-1
728
1589
answer


Pythonで数値をバイナリに吐き出す方法を2つ説明したいと思います。
まず、何らかの方法でデータを得て、以下のような形でfloatのリストで持っているとします。

[code]

    data = [0.1, 0.2, 0.3]
    
[/code]

## struct.pack を使う方法

[code]

    import struct
    with open('binaryVec.bin', 'wb') as f:
        for x in data:
            four_bytes = struct.pack('f', x)
            f.write(four_bytes)
    
[/code]

  * [packのformat characterの種類と意味](http://docs.python.org/2/library/struct.html#format-characters)

## numpy arrray の tofile メソッドを使う方法

上記の方法はforループを使うので、スピードが遅いです。 tofileメッソッドを使うと一気にバイナリファイルに書き出すことができます。

[code]

    import numpy as np
    X = np.array(data, dtype='float32')
    X.tofile('binaryVec.bin')
    
[/code]

今の場合、この2つの方法で作られた`binaryVec.bin`ファイルは全く同じものになります。 (32bit floatで保存されている)

* * *

補足: テキストファイルの読み出しについて

`Vec.txt`が以下のような形式で与えられているとします。(エントリがスペースで区切られている)

[code]

    日本語 0.1 0.2 0.3 
    
[/code]

このファイルをparseする1つの簡単な方法としては、`csv.reader`を使うことです。

[code]

    import csv
    with open('Vec.txt', 'rt') as g:
        for row in csv.reader(g, delimiter=' '):  # 入力ファイルは一行しか無いので、これでrowに全データが入る。
            pass
    data = map(float, row[1:])  # これで、data = [0.1, 0.2, 0.3] になる。
    
[/code]


CC BY-SA 3.0
2014-12-14T05:54:49.377
1591
2014-12-14T07:10:38.483
2014-12-14T07:10:38.483
848
848
1589
answer