Skip to content

Commit 3a0489e

Browse files
JimClarke5rnett
andauthored
Metrics Phase 1 (tensorflow#180)
* Initial checkin * Initial checkin and sync with master * Initial checkin and sync with master * JavaDoc cleanup * Javadoc fixes * Change LossInterface to LossMetric. Fix JavaDoc, modify one line code block to include braces. * Removed hashmap for variables, they are not needed as the variables only live within a single instance of a Metric. * reformat code * Add tests for assertBroadcastable * Change type to resultType * Added V data type for sampleWeights so that it is not forced to be the same type as the return or internal variables, * change 'type' to 'resultType' * clean up mean and fix assert assertBroadcastable * fix error message * Change sampleWeights to have its own generic type <S extends TNumber> * Add commment about invalid tests expecting IllegalArgumentExceptions * Add this exception instead of the more generic IllegalArgumentException when static shapes cannot boradcast. * change IllegalArgumentException to NotBroadcastableException. change hasValidNonscalarShape to canBroadcastNonscalarShapes change hasValidNonscalarShape to canBroadcastNonscalarShapes * reformat code * Fis=x Javadoc move the dynamic shapes and rank down to the dynamic section so they are created needlessly when static Fix if statement to check for unknown size and unknown dimensions * Fix Reduce to use boradcastWeights, renamed WeightBroadcastTest to AssertBroadcastableTest and added BroadcastWeightsTest * Added comment to count to indicate that it may be weighted. * Added SetsOps and fixed AssertBroadcastable to use SetsOps methods, * Fixed based on various PR comments. * Deleted, no longer needed after change to Variable handling in Metrics. * Nicer error messages for mode-forbidden ops (tensorflow#169) * start fobbiden ops checks Signed-off-by: Ryan Nett <[email protected]> * fix style Signed-off-by: Ryan Nett <[email protected]> * move checks to builder method Signed-off-by: Ryan Nett <[email protected]> * Initialization imprvements (tensorflow#178) * No-op on initAdd in eager mode Signed-off-by: Ryan Nett <[email protected]> * runInit() method in session Signed-off-by: Ryan Nett <[email protected]> * add doInitialization() to Runner Signed-off-by: Ryan Nett <[email protected]> * fix javadoc Signed-off-by: Ryan Nett <[email protected]> * assume only graph or eager environments Signed-off-by: Ryan Nett <[email protected]> * Remove doInit(), update javadocs Signed-off-by: Ryan Nett <[email protected]> * small fixes Signed-off-by: Ryan Nett <[email protected]> * Clairify tensorOf lifetime requirements (tensorflow#190) * Clairify tensorOf lifetime requirements Signed-off-by: Ryan Nett <[email protected]> * Do codegen Signed-off-by: Ryan Nett <[email protected]> * Remove extra generics from op generation (tensorflow#193) * Successfully remove extra type params, but it broke javadoc generation Signed-off-by: Ryan Nett <[email protected]> * Generate covariant types Signed-off-by: Ryan Nett <[email protected]> * Do generation Signed-off-by: Ryan Nett <[email protected]> * Update help text. Signed-off-by: Ryan Nett <[email protected]> * Fixes Signed-off-by: Ryan Nett <[email protected]> * Add Java 11 support - Initial Phase (tensorflow#185) * Add profile for JDK11 and Automatic-Module-Name to jars * add maven.compiler.release=11 * Update manual ops for new codegen (tensorflow#196) Signed-off-by: Ryan Nett <[email protected]> * Fix Losses to use CHANNELS_FIRST/LAST for CategoricalCrossentropy * Fix SetOps to properly convert sparse tensor to dense tensor using tf.sparse.sparseToDense with the output of tf.sparse.denseToDenseSetOperation * Initial checkin * Initial checkin and sync with master * Initial checkin and sync with master * JavaDoc cleanup * Javadoc fixes * Change LossInterface to LossMetric. Fix JavaDoc, modify one line code block to include braces. * Removed hashmap for variables, they are not needed as the variables only live within a single instance of a Metric. * reformat code * Add tests for assertBroadcastable * Change type to resultType * Added V data type for sampleWeights so that it is not forced to be the same type as the return or internal variables, * change 'type' to 'resultType' * clean up mean and fix assert assertBroadcastable * fix error message * Change sampleWeights to have its own generic type <S extends TNumber> * Add commment about invalid tests expecting IllegalArgumentExceptions * Add this exception instead of the more generic IllegalArgumentException when static shapes cannot boradcast. * change IllegalArgumentException to NotBroadcastableException. change hasValidNonscalarShape to canBroadcastNonscalarShapes change hasValidNonscalarShape to canBroadcastNonscalarShapes * reformat code * Fis=x Javadoc move the dynamic shapes and rank down to the dynamic section so they are created needlessly when static Fix if statement to check for unknown size and unknown dimensions * Fix Reduce to use boradcastWeights, renamed WeightBroadcastTest to AssertBroadcastableTest and added BroadcastWeightsTest * Added comment to count to indicate that it may be weighted. * Added SetsOps and fixed AssertBroadcastable to use SetsOps methods, * Fixed based on various PR comments. * Deleted, no longer needed after change to Variable handling in Metrics. * Fix Losses to use CHANNELS_FIRST/LAST for CategoricalCrossentropy * Fix SetOps to properly convert sparse tensor to dense tensor using tf.sparse.sparseToDense with the output of tf.sparse.denseToDenseSetOperation Co-authored-by: Ryan Nett <[email protected]>
1 parent 496191d commit 3a0489e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+4497
-18
lines changed

tensorflow-framework/src/main/java/org/tensorflow/framework/losses/CategoricalCrossentropy.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
public class CategoricalCrossentropy extends Loss {
7070
public static final boolean FROM_LOGITS_DEFAULT = false;
7171
public static final float LABEL_SMOOTHING_DEFAULT = 0.0f;
72-
public static final int DEFAULT_AXIS = -1;
72+
public static final int DEFAULT_AXIS = Losses.CHANNELS_LAST;
7373

7474
private final boolean fromLogits;
7575
private final float labelSmoothing;
@@ -203,8 +203,9 @@ public CategoricalCrossentropy(
203203
* confidence on label values are relaxed. e.g. <code>labelSmoothing=0.2</code> means that we will use a
204204
* value of <code>0.1</code> for label <code>0</code> and <code>0.9</code> for label <code>1</code>
205205
* @param reduction Type of Reduction to apply to loss.
206-
* @param axis The channels axis. <code>axis=-1</code> corresponds to data format `Channels Last'
207-
* and <code>axis=1</code> corresponds to data format 'Channels First'.
206+
* @param axis The channels axis. <code>axis=-1</code> corresponds to data format "Channels Last"
207+
* and <code>axis=1</code> corresponds to data format "Channels First".
208+
* {@link Losses#CHANNELS_LAST} and {@link Losses#CHANNELS_FIRST}
208209
* @throws IllegalArgumentException if labelSmoothing is not in the inclusive range of 0. - 1.
209210
*/
210211
public CategoricalCrossentropy(

tensorflow-framework/src/main/java/org/tensorflow/framework/losses/Losses.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ public class Losses {
3636
/** Default Fuzz factor. */
3737
public static final float EPSILON = 1e-7f;
3838

39+
public static final int CHANNELS_LAST = -1;
40+
public static final int CHANNELS_FIRST = 1;
41+
3942
/**
4043
* Calculates the mean absolute error between labels and predictions.
4144
*
@@ -239,7 +242,7 @@ public static <T extends TNumber, U extends TNumber> Operand<T> categoricalCross
239242
tLabels = smoothCategoricalLabels(tf, tLabels, labelSmoothing);
240243
}
241244
if (fromLogits) {
242-
return tf.nn.softmaxCrossEntropyWithLogits(tLabels, predictions, -1);
245+
return tf.nn.softmaxCrossEntropyWithLogits(tLabels, predictions, axis);
243246
}
244247
/* TODO
245248
if (!(predictions instanceof Variable) && (!tf.scope().env().isEager())) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
=======================================================================*/
15+
package org.tensorflow.framework.metrics;
16+
17+
import org.tensorflow.Operand;
18+
import org.tensorflow.framework.losses.Losses;
19+
import org.tensorflow.framework.metrics.impl.LossMetric;
20+
import org.tensorflow.framework.metrics.impl.MeanMetricWrapper;
21+
import org.tensorflow.op.Ops;
22+
import org.tensorflow.types.family.TNumber;
23+
24+
/**
25+
* A Metric that computes the binary cross-entropy loss between true labels and predicted labels.
26+
*
27+
* <p>This is the crossentropy metric class to be used when there are only two label classes (0 and
28+
* 1).
29+
*
30+
* @param <U> the data type for the predictions.
31+
* @param <T> The data type for the metric result
32+
*/
33+
public class BinaryCrossentropy<U extends TNumber, T extends TNumber>
34+
extends MeanMetricWrapper<U, T> implements LossMetric<T> {
35+
36+
private final boolean fromLogits;
37+
private final float labelSmoothing;
38+
39+
/**
40+
* Creates a BinaryCrossentropy metric
41+
*
42+
* @param tf the TensorFlow Ops
43+
* @param name the name of this metric, if null then metric name is {@link Class#getSimpleName()}.
44+
* @param fromLogits Whether to interpret predictions as a tensor of logit values as opposed to a probability distribution.
45+
* @param labelSmoothing value used to smooth labels, When 0, no smoothing occurs. When &gt; 0,
46+
* compute the loss between the predicted labels and a smoothed version of the true labels,
47+
* where the smoothing squeezes the labels towards 0.5. Larger values of label_smoothing
48+
* correspond to heavier smoothing.
49+
* @param seed the seed for random number generation. An initializer created with a given seed
50+
* will always produce the same random tensor for a given shape and data type.
51+
* @param type the type for the variables and result
52+
*/
53+
public BinaryCrossentropy(
54+
Ops tf, String name, boolean fromLogits, float labelSmoothing, long seed, Class<T> type) {
55+
super(tf, name, seed, type);
56+
setLoss(this);
57+
this.fromLogits = fromLogits;
58+
this.labelSmoothing = labelSmoothing;
59+
}
60+
61+
/** {@inheritDoc} */
62+
@Override
63+
public <V extends TNumber> Operand<T> call(Operand<V> labels, Operand<T> predictions) {
64+
return Losses.binaryCrossentropy(getTF(), labels, predictions, fromLogits, labelSmoothing);
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
=======================================================================*/
15+
package org.tensorflow.framework.metrics;
16+
17+
import org.tensorflow.Operand;
18+
import org.tensorflow.framework.losses.Losses;
19+
import org.tensorflow.framework.metrics.impl.LossMetric;
20+
import org.tensorflow.framework.metrics.impl.MeanMetricWrapper;
21+
import org.tensorflow.op.Ops;
22+
import org.tensorflow.types.family.TNumber;
23+
24+
/**
25+
* A Metric that computes the categorical cross-entropy loss between true labels and predicted
26+
* labels.
27+
*
28+
* <p>This is the crossentropy metric class to be used when there are multiple label classes (2 or
29+
* more). The labels should be given as a one_hot representation. eg., When labels values are <code>
30+
* [2, 0, 1]</code>, the labels Operand contains = <code>[[0, 0, 1], [1, 0, 0], [0, 1, 0]]
31+
* </code>.
32+
*
33+
* @param <U> the data type for the predictions.
34+
* @param <T> The data type for the metric result
35+
*/
36+
public class CategoricalCrossentropy<U extends TNumber, T extends TNumber>
37+
extends MeanMetricWrapper<U, T> implements LossMetric<T> {
38+
39+
private final boolean fromLogits;
40+
private final float labelSmoothing;
41+
private final int axis;
42+
43+
/**
44+
* Creates a CategoricalCrossentropy metric that computes the crossentropy metric between the
45+
* labels and predictions.
46+
*
47+
* <p>Uses a {@link Losses#CHANNELS_LAST} for the channel axis.
48+
*
49+
* @param tf the TensorFlow Ops
50+
* @param name the name of this metric, if null then metric name is {@link Class#getSimpleName()}.
51+
* @param fromLogits Whether to interpret predictions as a tensor of logit values oras opposed to a probability distribution.
52+
* @param labelSmoothing value used to smooth labels, When &gt; 0, label values are smoothed,
53+
* meaning the confidence on label values are relaxed. e.g. <code>labelSmoothing=0.2</code>
54+
* means that we will use a value of <code>0.1</code> for label <code>0</code> and <code>0.9
55+
* </code> for label <code>1</code>
56+
* @param seed the seed for random number generation. An initializer created with a given seed
57+
* will always produce the same random tensor for a given shape and data type.
58+
* @param type the type for the variables and result
59+
*/
60+
public CategoricalCrossentropy(
61+
Ops tf, String name, boolean fromLogits, float labelSmoothing, long seed, Class<T> type) {
62+
this(tf, name, fromLogits, labelSmoothing, Losses.CHANNELS_LAST, seed, type);
63+
}
64+
65+
/**
66+
* Creates a CategoricalCrossentropy metric that computes the crossentropy metric between the
67+
* labels and predictions.
68+
*
69+
* @param tf the TensorFlow Ops
70+
* @param name the name of this metric, if null then metric name is {@link Class#getSimpleName()}.
71+
* @param fromLogits Whether to interpret predictions as a tensor of logit values as opposed to a probability distribution.
72+
* @param labelSmoothing value used to smooth labels, When &gt; 0, label values are smoothed,
73+
* meaning the confidence on label values are relaxed. e.g. <code>labelSmoothing=0.2</code>
74+
* means that we will use a value of <code>0.1</code> for label <code>0</code> and <code>0.9
75+
* </code> for label <code>1</code>
76+
* @param axis Int specifying the channels axis. <code>axis={@link Losses#CHANNELS_LAST}</code>
77+
* corresponds to data format <code>channels_last</code>, and <code>
78+
* axis={@link Losses#CHANNELS_FIRST}</code> corresponds to data format <code>
79+
* channels_first</code>.
80+
* @param seed the seed for random number generation. An initializer created with a given seed
81+
* will always produce the same random tensor for a given shape and data type.
82+
* @param type the type for the variables and result
83+
*/
84+
public CategoricalCrossentropy(
85+
Ops tf,
86+
String name,
87+
boolean fromLogits,
88+
float labelSmoothing,
89+
int axis,
90+
long seed,
91+
Class<T> type) {
92+
super(tf, name, seed, type);
93+
setLoss(this);
94+
this.fromLogits = fromLogits;
95+
this.labelSmoothing = labelSmoothing;
96+
this.axis = axis;
97+
}
98+
99+
/** {@inheritDoc} */
100+
@Override
101+
public <V extends TNumber> Operand<T> call(Operand<V> labels, Operand<T> predictions) {
102+
return Losses.categoricalCrossentropy(
103+
getTF(), labels, predictions, fromLogits, labelSmoothing, axis);
104+
}
105+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
=======================================================================*/
15+
package org.tensorflow.framework.metrics;
16+
17+
import org.tensorflow.Operand;
18+
import org.tensorflow.framework.losses.Losses;
19+
import org.tensorflow.framework.metrics.impl.LossMetric;
20+
import org.tensorflow.framework.metrics.impl.MeanMetricWrapper;
21+
import org.tensorflow.op.Ops;
22+
import org.tensorflow.types.family.TNumber;
23+
24+
/**
25+
* A Metric that computes the categorical hinge loss metric between labels and predictions.
26+
*
27+
* @param <U> the data type for the predictions.
28+
* @param <T> The data type for the metric result
29+
*/
30+
public class CategoricalHinge<U extends TNumber, T extends TNumber> extends MeanMetricWrapper<U, T>
31+
implements LossMetric<T> {
32+
33+
/**
34+
* Creates a CategoricalHinge metric
35+
*
36+
* @param tf the TensorFlow Ops
37+
* @param name the name of this metric, if null then metric name is {@link Class#getSimpleName()}.
38+
* @param seed the seed for random number generation. An initializer created with a given seed
39+
* will always produce the same random tensor for a given shape and data type.
40+
* @param type the type for the variables and result
41+
*/
42+
public CategoricalHinge(Ops tf, String name, long seed, Class<T> type) {
43+
super(tf, name, seed, type);
44+
setLoss(this);
45+
}
46+
47+
/** {@inheritDoc} */
48+
@Override
49+
public <V extends TNumber> Operand<T> call(Operand<V> labels, Operand<T> predictions) {
50+
return Losses.categoricalHinge(getTF(), labels, predictions);
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
=======================================================================*/
15+
package org.tensorflow.framework.metrics;
16+
17+
import org.tensorflow.Operand;
18+
import org.tensorflow.framework.metrics.impl.LossMetric;
19+
import org.tensorflow.framework.metrics.impl.MeanMetricWrapper;
20+
import org.tensorflow.op.Ops;
21+
import org.tensorflow.types.family.TNumber;
22+
23+
/**
24+
* A metric that computes the cosine similarity metric between labels and predictions.
25+
*
26+
* @param <U> the data type for the predictions.
27+
* @param <T> The data type for the metric result.
28+
*/
29+
public class CosineSimilarity<U extends TNumber, T extends TNumber> extends MeanMetricWrapper<U, T>
30+
implements LossMetric<T> {
31+
public static final int DEFAULT_AXIS = -1;
32+
private final int[] axis;
33+
34+
/**
35+
* Creates a metric that computes the cosine similarity metric between labels and predictions with
36+
* a default axis, {@link #DEFAULT_AXIS}
37+
*
38+
* @param tf the TensorFlow Ops
39+
* @param name the name of this metric, if null then metric name is {@link Class#getSimpleName()}.
40+
* @param seed the seed for random number generation. An initializer created with a given seed
41+
* will always produce the same random tensor for a given shape and data type.
42+
* @param type the type for the variables and result
43+
*/
44+
public CosineSimilarity(Ops tf, String name, long seed, Class<T> type) {
45+
this(tf, name, DEFAULT_AXIS, seed, type);
46+
}
47+
48+
/**
49+
* Creates a metric that computes the cosine similarity metric between labels and predictions.
50+
*
51+
* @param tf the TensorFlow Ops
52+
* @param name the name of this metric, if null then metric name is {@link Class#getSimpleName()}.
53+
* @param axis The dimension along which the cosine similarity is computed.
54+
* @param seed the seed for random number generation. An initializer created with a given seed
55+
* will always produce the same random tensor for a given shape and data type.
56+
* @param type the type for the variables and result
57+
*/
58+
public CosineSimilarity(Ops tf, String name, int axis, long seed, Class<T> type) {
59+
this(tf, name, new int[] {axis}, seed, type);
60+
}
61+
/**
62+
* Creates a CosineSimilarity metric
63+
*
64+
* @param tf the TensorFlow Ops
65+
* @param name the name of this metric, if null then metric name is {@link Class#getSimpleName()}.
66+
* @param axis The dimension along which the cosine similarity is computed.
67+
* @param seed the seed for random number generation. An initializer created with a given seed
68+
* will always produce the same random tensor for a given shape and data type.
69+
* @param type the type for the variables and result
70+
*/
71+
public CosineSimilarity(Ops tf, String name, int[] axis, long seed, Class<T> type) {
72+
super(tf, name, seed, type);
73+
this.axis = axis;
74+
setLoss(this);
75+
}
76+
77+
/** {@inheritDoc} */
78+
@Override
79+
public <V extends TNumber> Operand<T> call(Operand<V> labels, Operand<T> predictions) {
80+
// NOTE: cosineProximity is a different algorithm than Losses.cosineSimilarity
81+
return Metrics.cosineProximity(getTF(), labels, predictions, axis);
82+
}
83+
}

0 commit comments

Comments
 (0)