"llama/patches/0011-ollama-debug-tensor.patch" did not exist on "9e4642e9b3e9a26d423c62915805375ca253d7d1"
ncf_test.py 10.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Copyright 2018 The TensorFlow Authors. 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.
# ==============================================================================
"""Tests NCF."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import math
22
import unittest
23
24
25

import numpy as np
import tensorflow as tf
Hongkun Yu's avatar
Hongkun Yu committed
26
from tensorflow.python.eager import context  # pylint: disable=ungrouped-imports
27
from official.recommendation import constants as rconst
28
from official.recommendation import data_pipeline
Shining Sun's avatar
Shining Sun committed
29
from official.recommendation import ncf_common
30
from official.recommendation import ncf_keras_main
Hongkun Yu's avatar
Hongkun Yu committed
31
from official.recommendation import neumf_model
32
from official.utils.misc import keras_utils
33
from official.utils.testing import integration
34

35
36

NUM_TRAIN_NEG = 4
37
38
39


class NcfTest(tf.test.TestCase):
Reed's avatar
Reed committed
40
41
42
43

  @classmethod
  def setUpClass(cls):  # pylint: disable=invalid-name
    super(NcfTest, cls).setUpClass()
Shining Sun's avatar
Shining Sun committed
44
    ncf_common.define_ncf_flags()
Reed's avatar
Reed committed
45

46
47
48
49
50
51
52
53
54
  def setUp(self):
    self.top_k_old = rconst.TOP_K
    self.num_eval_negatives_old = rconst.NUM_EVAL_NEGATIVES
    rconst.NUM_EVAL_NEGATIVES = 2

  def tearDown(self):
    rconst.NUM_EVAL_NEGATIVES = self.num_eval_negatives_old
    rconst.TOP_K = self.top_k_old

55
  @unittest.skipIf(keras_utils.is_v2_0(), "TODO(b/136018594)")
56
57
58
59
  def get_hit_rate_and_ndcg(self, predicted_scores_by_user, items_by_user,
                            top_k=rconst.TOP_K, match_mlperf=False):
    rconst.TOP_K = top_k
    rconst.NUM_EVAL_NEGATIVES = predicted_scores_by_user.shape[1] - 1
60
61
62
63
64
65
66
    batch_size = items_by_user.shape[0]

    users = np.repeat(np.arange(batch_size)[:, np.newaxis],
                      rconst.NUM_EVAL_NEGATIVES + 1, axis=1)
    users, items, duplicate_mask = \
      data_pipeline.BaseDataConstructor._assemble_eval_batch(
          users, items_by_user[:, -1:], items_by_user[:, :-1], batch_size)
67
68
69
70
71
72
73

    g = tf.Graph()
    with g.as_default():
      logits = tf.convert_to_tensor(
          predicted_scores_by_user.reshape((-1, 1)), tf.float32)
      softmax_logits = tf.concat([tf.zeros(logits.shape, dtype=logits.dtype),
                                  logits], axis=1)
74
      duplicate_mask = tf.convert_to_tensor(duplicate_mask, tf.float32)
75

Shining Sun's avatar
Shining Sun committed
76
      metric_ops = neumf_model._get_estimator_spec_with_metrics(
77
78
79
80
81
82
83
          logits=logits, softmax_logits=softmax_logits,
          duplicate_mask=duplicate_mask, num_training_neg=NUM_TRAIN_NEG,
          match_mlperf=match_mlperf).eval_metric_ops

      hr = metric_ops[rconst.HR_KEY]
      ndcg = metric_ops[rconst.NDCG_KEY]

84
85
      init = [tf.compat.v1.global_variables_initializer(),
              tf.compat.v1.local_variables_initializer()]
86

87
    with self.session(graph=g) as sess:
88
89
90
      sess.run(init)
      return sess.run([hr[1], ndcg[1]])

91
92
93
  def test_hit_rate_and_ndcg(self):
    # Test with no duplicate items
    predictions = np.array([
94
95
96
97
        [2., 0., 1.],  # In top 2
        [1., 0., 2.],  # In top 1
        [2., 1., 0.],  # In top 3
        [3., 4., 2.]   # In top 3
98
99
100
    ])
    items = np.array([
        [2, 3, 1],
101
        [3, 1, 2],
102
        [2, 1, 3],
103
        [1, 3, 2],
104
    ])
105
106

    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 1)
107
108
    self.assertAlmostEqual(hr, 1 / 4)
    self.assertAlmostEqual(ndcg, 1 / 4)
109
110

    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 2)
111
112
    self.assertAlmostEqual(hr, 2 / 4)
    self.assertAlmostEqual(ndcg, (1 + math.log(2) / math.log(3)) / 4)
113
114

    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 3)
115
116
117
118
    self.assertAlmostEqual(hr, 4 / 4)
    self.assertAlmostEqual(ndcg, (1 + math.log(2) / math.log(3) +
                                  2 * math.log(2) / math.log(4)) / 4)

119
120
    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 1,
                                          match_mlperf=True)
121
122
    self.assertAlmostEqual(hr, 1 / 4)
    self.assertAlmostEqual(ndcg, 1 / 4)
123
124
125

    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 2,
                                          match_mlperf=True)
126
127
    self.assertAlmostEqual(hr, 2 / 4)
    self.assertAlmostEqual(ndcg, (1 + math.log(2) / math.log(3)) / 4)
128
129
130

    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 3,
                                          match_mlperf=True)
131
132
133
134
135
136
137
    self.assertAlmostEqual(hr, 4 / 4)
    self.assertAlmostEqual(ndcg, (1 + math.log(2) / math.log(3) +
                                  2 * math.log(2) / math.log(4)) / 4)

    # Test with duplicate items. In the MLPerf case, we treat the duplicates as
    # a single item. Otherwise, we treat the duplicates as separate items.
    predictions = np.array([
138
139
140
141
        [2., 2., 3., 1.],  # In top 4. MLPerf: In top 3
        [1., 0., 2., 3.],  # In top 1. MLPerf: In top 1
        [2., 3., 2., 0.],  # In top 4. MLPerf: In top 3
        [2., 4., 2., 3.]   # In top 2. MLPerf: In top 2
142
143
    ])
    items = np.array([
144
145
146
147
        [2, 2, 3, 1],
        [2, 3, 4, 1],
        [2, 3, 2, 1],
        [3, 2, 1, 4],
148
    ])
149
    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 1)
150
151
    self.assertAlmostEqual(hr, 1 / 4)
    self.assertAlmostEqual(ndcg, 1 / 4)
152
153

    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 2)
154
155
    self.assertAlmostEqual(hr, 2 / 4)
    self.assertAlmostEqual(ndcg, (1 + math.log(2) / math.log(3)) / 4)
156
157

    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 3)
158
159
    self.assertAlmostEqual(hr, 2 / 4)
    self.assertAlmostEqual(ndcg, (1 + math.log(2) / math.log(3)) / 4)
160
161

    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 4)
162
163
164
165
    self.assertAlmostEqual(hr, 4 / 4)
    self.assertAlmostEqual(ndcg, (1 + math.log(2) / math.log(3) +
                                  2 * math.log(2) / math.log(5)) / 4)

166
167
    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 1,
                                          match_mlperf=True)
168
169
    self.assertAlmostEqual(hr, 1 / 4)
    self.assertAlmostEqual(ndcg, 1 / 4)
170
171
172

    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 2,
                                          match_mlperf=True)
173
174
    self.assertAlmostEqual(hr, 2 / 4)
    self.assertAlmostEqual(ndcg, (1 + math.log(2) / math.log(3)) / 4)
175
176
177

    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 3,
                                          match_mlperf=True)
178
179
180
    self.assertAlmostEqual(hr, 4 / 4)
    self.assertAlmostEqual(ndcg, (1 + math.log(2) / math.log(3) +
                                  2 * math.log(2) / math.log(4)) / 4)
181
182
183

    hr, ndcg = self.get_hit_rate_and_ndcg(predictions, items, 4,
                                          match_mlperf=True)
184
185
186
187
    self.assertAlmostEqual(hr, 4 / 4)
    self.assertAlmostEqual(ndcg, (1 + math.log(2) / math.log(3) +
                                  2 * math.log(2) / math.log(4)) / 4)

188
  _BASE_END_TO_END_FLAGS = ['-batch_size', '1044', '-train_epochs', '1']
189

190
  @unittest.mock.patch.object(rconst, "SYNTHETIC_BATCHES_PER_EPOCH", 100)
191
  def test_end_to_end_keras_no_dist_strat(self):
192
    integration.run_synthetic(
193
        ncf_keras_main.main, tmp_root=self.get_temp_dir(),
194
        extra_flags=self._BASE_END_TO_END_FLAGS +
195
        ['-distribution_strategy', 'off'])
Reed's avatar
Reed committed
196

197
  @unittest.mock.patch.object(rconst, "SYNTHETIC_BATCHES_PER_EPOCH", 100)
guptapriya's avatar
guptapriya committed
198
  @unittest.skipUnless(keras_utils.is_v2_0(), 'TF 2.0 only test.')
199
  def test_end_to_end_keras_dist_strat(self):
200
    integration.run_synthetic(
201
        ncf_keras_main.main, tmp_root=self.get_temp_dir(),
202
203
        extra_flags=self._BASE_END_TO_END_FLAGS + ['-num_gpus', '0'])

204
  @unittest.mock.patch.object(rconst, "SYNTHETIC_BATCHES_PER_EPOCH", 100)
guptapriya's avatar
guptapriya committed
205
  @unittest.skipUnless(keras_utils.is_v2_0(), 'TF 2.0 only test.')
206
207
208
209
210
  def test_end_to_end_keras_dist_strat_ctl(self):
    flags = (self._BASE_END_TO_END_FLAGS +
             ['-num_gpus', '0'] +
             ['-keras_use_ctl', 'True'])
    integration.run_synthetic(
211
        ncf_keras_main.main, tmp_root=self.get_temp_dir(),
guptapriya's avatar
guptapriya committed
212
        extra_flags=flags)
Reed's avatar
Reed committed
213

214
  @unittest.mock.patch.object(rconst, "SYNTHETIC_BATCHES_PER_EPOCH", 100)
guptapriya's avatar
guptapriya committed
215
  @unittest.skipUnless(keras_utils.is_v2_0(), 'TF 2.0 only test.')
216
  def test_end_to_end_keras_1_gpu_dist_strat_fp16(self):
217
218
219
220
221
222
    if context.num_gpus() < 1:
      self.skipTest(
          "{} GPUs are not available for this test. {} GPUs are available".
          format(1, context.num_gpus()))

    integration.run_synthetic(
223
        ncf_keras_main.main, tmp_root=self.get_temp_dir(),
224
225
        extra_flags=self._BASE_END_TO_END_FLAGS + ['-num_gpus', '1',
                                                   '--dtype', 'fp16'])
226

227
  @unittest.mock.patch.object(rconst, "SYNTHETIC_BATCHES_PER_EPOCH", 100)
guptapriya's avatar
guptapriya committed
228
  @unittest.skipUnless(keras_utils.is_v2_0(), 'TF 2.0 only test.')
229
230
231
232
233
234
235
236
237
238
239
240
  def test_end_to_end_keras_1_gpu_dist_strat_ctl_fp16(self):
    if context.num_gpus() < 1:
      self.skipTest(
          '{} GPUs are not available for this test. {} GPUs are available'.
          format(1, context.num_gpus()))

    integration.run_synthetic(
        ncf_keras_main.main, tmp_root=self.get_temp_dir(),
        extra_flags=self._BASE_END_TO_END_FLAGS + ['-num_gpus', '1',
                                                   '--dtype', 'fp16',
                                                   '--keras_use_ctl'])

241
  @unittest.mock.patch.object(rconst, 'SYNTHETIC_BATCHES_PER_EPOCH', 100)
242
243
  @unittest.skipUnless(keras_utils.is_v2_0(), 'TF 2.0 only test.')
  def test_end_to_end_keras_2_gpu_fp16(self):
244
245
246
247
248
249
    if context.num_gpus() < 2:
      self.skipTest(
          "{} GPUs are not available for this test. {} GPUs are available".
          format(2, context.num_gpus()))

    integration.run_synthetic(
250
        ncf_keras_main.main, tmp_root=self.get_temp_dir(),
251
252
        extra_flags=self._BASE_END_TO_END_FLAGS + ['-num_gpus', '2',
                                                   '--dtype', 'fp16'])
253
254
255

if __name__ == "__main__":
  tf.test.main()