Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make word2vec2tensor script compatible with python3 #2147

Merged
merged 8 commits into from
Aug 14, 2018

Conversation

vsocrates
Copy link
Contributor

Fixes #1958. The word2vec2tensor script didn't support Python 3 due to unicode encoding. This was fixed and tests were added to ensure that the script functions correctly in the future. The usage of the script on the user side remains the same.

Copy link
Contributor

@menshikh-iv menshikh-iv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for PR @vsocrates, please continue 👍 you are on right way!

@@ -63,16 +67,15 @@ def word2vec2tensor(word2vec_model_path, tensor_filename, binary=False):
True if input file in binary format.

"""
model = gensim.models.KeyedVectors.load_word2vec_format(word2vec_model_path, binary=binary)
model = gensim.models.KeyedVectors.load_word2vec_format(word2vec_model_path, binary=binary, datatype=np.float64)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why np.float64 instead of np.float32 (that's default parameter)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason, when the word2vec model is loaded, if we leave the default, using the test data file word2vec_pre_kv_c I run into parsing issues. For instance, for the word the, I get array([-0.56110603, -1.97569799, 1.66395497, -1.23224604, 0.75475103, 0.98576403, 2.26144099, -0.59829003, -0.47433099, -1.41610503], dtype=float32) instead of -0.561106 -1.975698 1.663955 -1.232246 0.754751 0.985764 2.261441 -0.598290 -0.474331 -1.416105

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And what's a problem here? I still don't catch, sorry

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, should have been more clear. In the first dimension, as an example, the original word2vec model has -0.561106 but for some reason, without the np.float64 when it is read in, it displays -0.56110603, so the test fails equality. I'm not sure on the reason, though I assume something to do with the load_word2vec_format internals.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's assertion you mean? can you link concrete line of code?

Also, you can fix assertion (slightly relax "almost equal" condition), but anyway, you shouldn't change dtype here.

class TestWord2Vec2Tensor(unittest.TestCase):
def setUp(self):
self.datapath = datapath('word2vec_pre_kv_c')
self.output_folder = get_tmpfile('')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to add an explicit name (for example w2v2t_test)

def testConversion(self):
word2vec2tensor(word2vec_model_path=self.datapath, tensor_filename=self.output_folder)

try:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need try/except in current test. if exception raised - test failed, this is expected behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without try/except, should we give the developers more feedback and which part of test went wrong? If so, how would I do that without the except block?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not in the current case, stack trace (if something goes wrong) have enough information in current tests.

first_line = f.readline().strip()

number_words, vector_size = map(int, first_line.split(b' '))
if not len(metadata) == len(vectors) == number_words:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert <CONDITION>, <MESSAGE>

number_words, vector_size = map(int, first_line.split(b' '))
if not len(metadata) == len(vectors) == number_words:
self.fail(
'Metadata file %s and tensor file %s \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we using 120 character limit, no reasons to make short lines

imply different number of rows.' % (self.metadata_file, self.tensor_file)
)

# write word2vec to file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The strange part of the test, you copy part of the code from script to test this script, why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm, sorry, could you be a bit more specific? Do you mean the lines from 154-157? If so, the idea was to take the metadata and tensor components that were separated and put the back together in w2v style without any gensim functions and make sure they are the same as what is created by the word2vec2tensor.py script. I guess it is basically just tested to_utf8 though. Is it fine to remove it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to remove it, yes

@menshikh-iv menshikh-iv changed the title W2v2tensor Make word2vec2tensor script compatible with python3 Aug 10, 2018
@vsocrates
Copy link
Contributor Author

vsocrates commented Aug 11, 2018

@menshikh-iv The changes you mentioned have been made.

With regards to the float32 issue, I thought it'd be easier if I showed you the issue I was getting. The CI tests below show what happens when I don't include the float64 data type. The np.testing module tests to 7 decimal places, and what is in the original file vs. what is written to the two tensor files differs by less than 7 decimal places in the following assertion

@menshikh-iv
Copy link
Contributor

@vsocrates ok, I see, simply "relax" decimal parameter of assert_almost_equal function (to 6 or 5), that's not an big deal (and I can merge current PR after CI are passed).

@menshikh-iv
Copy link
Contributor

menshikh-iv commented Aug 14, 2018

Thank you @vsocrates, congrats on the first contribution 🥇 !

@menshikh-iv menshikh-iv merged commit 27c524d into piskvorky:develop Aug 14, 2018
@vsocrates vsocrates deleted the w2v2tensor branch August 14, 2018 02:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

gensim.scripts.word2vec2tensor TypeError: write() argument must be str, not bytes
2 participants