Skip to content

Commit ccbe06a

Browse files
cesarsouzamigueldeicaza
authored andcommitted
Adding dropout as a graph operation (migueldeicaza#83)
* migueldeicazaGH-82: Adding Dropout as a Graph operation. * Adding one more unit test to test matrix addition (other test was testing only single values) * Ignoring files specific to VS and related tools. * Fixing a formatting issue (tabs instead of spaces in the documentation).
1 parent 2804490 commit ccbe06a

4 files changed

Lines changed: 133 additions & 2 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,6 @@ Thumbs.db
3838

3939
# dotCover
4040
*.dotCover
41+
42+
.vs
43+
*.GhostDoc.xml

TensorFlowSharp/OperationsExtras.cs

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ TFOutput ShapeTensorOutput (TFShape shape)
187187
/// <param name="mean">The mean of the standard distribution.</param>
188188
/// <param name="stddev">The standard deviation of the normal distribution.</param>
189189
/// <param name="seed">Integer seed used for the random distribution, using the TensorFlow SetRandomSeed .</param>
190-
/// <param name="operName">>Operation name, optional.</param>
190+
/// <param name="operName">Operation name, optional.</param>
191191
public TFOutput RandomNormal (TFShape shape, double mean = 0, double stddev = 1, int? seed = null, string operName = null)
192192
{
193193
var scopeName = MakeName ("RandomNormal", operName);
@@ -257,5 +257,67 @@ public void GetRandomSeeds (int? operationSeed, out int graphSeed, out int local
257257
}
258258
}
259259
}
260-
}
260+
261+
/// <summary>
262+
/// Computes dropout.
263+
/// </summary>
264+
/// <param name="x">A tensor.</param>
265+
/// <param name="keep_prob">A scalar Tensor with the same type as x. The probability that each element is kept.</param>
266+
/// <param name="noise_shape">A 1-D Tensor of type int32, representing the shape for randomly generated keep/drop flags.</param>
267+
/// <param name="seed">Integer seed used for the random distribution, using the TensorFlow SetRandomSeed .</param>
268+
/// <param name="operName">Operation name, optional.</param>
269+
/// <remarks>
270+
/// With probability keep_prob, outputs the input element scaled up by 1 / keep_prob,
271+
/// otherwise outputs 0. The scaling is so that the expected sum is unchanged.
272+
/// </remarks>
273+
public TFOutput Dropout (TFOutput x, TFOutput keep_prob, TFShape noise_shape = null, int? seed= null, string operName= null)
274+
{
275+
var scopeName = MakeName("dropout", operName);
276+
277+
using (var newScope = WithScope(scopeName)) {
278+
if (noise_shape == null)
279+
noise_shape = new TFShape(GetShape(x));
280+
281+
TFOutput shapeTensor = ShapeTensorOutput(noise_shape);
282+
283+
// uniform [keep_prob, 1.0 + keep_prob)
284+
TFOutput random_tensor = keep_prob;
285+
random_tensor = Add(random_tensor, RandomUniform(shapeTensor, seed: seed, dtype: x.OutputType));
286+
287+
// 0. if [keep_prob, 1.0) and 1. if [1.0, 1.0 + keep_prob)
288+
TFOutput binary_tensor = Floor(random_tensor);
289+
TFOutput ret = Mul(Div(x, keep_prob) , binary_tensor);
290+
SetTensorShape(ret, GetShape(x));
291+
return ret;
292+
}
293+
}
294+
295+
/// <summary>
296+
/// Computes dropout.
297+
/// </summary>
298+
/// <param name="x">A tensor.</param>
299+
/// <param name="keep_prob">A scalar Tensor with the same type as x. The probability that each element is kept.</param>
300+
/// <param name="noise_shape">A 1-D Tensor of type int32, representing the shape for randomly generated keep/drop flags.</param>
301+
/// <param name="seed">Integer seed used for the random distribution, using the TensorFlow SetRandomSeed .</param>
302+
/// <param name="operName">Operation name, optional.</param>
303+
/// <remarks>
304+
/// With probability keep_prob, outputs the input element scaled up by 1 / keep_prob,
305+
/// otherwise outputs 0. The scaling is so that the expected sum is unchanged.
306+
/// </remarks>
307+
public TFOutput Dropout (TFOutput x, double keep_prob, TFShape noise_shape = null, int? seed = null, string operName = null)
308+
{
309+
if (keep_prob < 0 || keep_prob >= 1)
310+
throw new ArgumentOutOfRangeException("keep_prob must be a scalar tensor or a float in the range (0, 1], got " + keep_prob);
311+
312+
if (keep_prob == 1)
313+
return x;
314+
315+
var scopeName = MakeName("dropout", operName);
316+
using (var newScope = WithScope(scopeName)) {
317+
var tkeep_prob = Const(keep_prob);
318+
return Dropout(x, tkeep_prob, noise_shape, seed, operName);
319+
}
320+
}
321+
}
322+
261323
}

tests/TensorFlowSharp.Tests/ArithmeticOperationTests.fs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,31 @@ module ArithmeticOperationTests =
2727
let mulValue = mulTensor.GetValue() :?> float32
2828

2929
Assert.Equal(expected, mulValue)
30+
31+
32+
[<Theory>]
33+
let Should_EvaluateAddExpression_ForFloatDataType() =
34+
use graph = new TFGraph()
35+
use session = new TFSession(graph)
36+
37+
let a = graph.Placeholder(TFDataType.Float) // create symbolic variable a
38+
let b = graph.Placeholder(TFDataType.Float) // create symbolic variable b
39+
40+
let y = graph.Mul(a, b) // multiply symbolic variables
41+
42+
let aValue = Array2D.init 40 20 (fun i j -> i)
43+
let bValue = Array2D.init 40 20 (fun i j -> i + j)
44+
let sValue = Array2D.init 40 20 (fun i j -> 2*i + j)
45+
46+
47+
// evaluate expression with parameters for a and b
48+
let add =
49+
session.Run([| a; b |],
50+
[| new TFTensor(aValue); new TFTensor(bValue) |],
51+
[| y |])
52+
53+
let addTensor = add.[0]
54+
let addValue = addTensor.GetValue() :?> int[,]
55+
let it = sValue = addValue : bool
56+
Assert.True(it);
57+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
namespace TensorFlowSharp.Tests
2+
3+
open TensorFlow
4+
open Xunit
5+
6+
module NeuralNetOperationTests =
7+
8+
[<Theory>]
9+
[<InlineData(0.1f)>]
10+
[<InlineData(0.5f)>]
11+
[<InlineData(1.0f)>]
12+
let Should_ApplyDropout_ForFloatDataType(keep_prob:float32) =
13+
use graph = new TFGraph()
14+
use session = new TFSession(graph)
15+
16+
let inputs = Array2D.init 4000 200 (fun i j -> float32(i+j+1))
17+
18+
let a = graph.Placeholder(TFDataType.Float, new TFShape(4000L, 200L)) // create symbolic variable x
19+
let b = graph.Placeholder(TFDataType.Float, new TFShape(4000L, 200L)) // create symbolic variable keep_prob
20+
21+
let y = graph.Dropout(a, b) // apply dropout to symbolic variables
22+
23+
// evaluate expression with parameters for a and b
24+
let res =
25+
session.Run([| a; b |],
26+
[| new TFTensor(inputs); new TFTensor(keep_prob) |],
27+
[| y |])
28+
29+
let resTensor = res.[0]
30+
let resValue = resTensor.GetValue() :?> float32[,]
31+
32+
let countZeros arr = arr |> Seq.cast<float32> |> Seq.filter (fun x -> x = 0.0f) |> Seq.length
33+
let numberOfOnes = countZeros resValue |> float32;
34+
let totalLength = resValue |> Seq.cast<float32> |> Seq.length |> float32
35+
let actualRatio = numberOfOnes / totalLength;
36+
let expected = 1.0f - keep_prob : float32
37+
38+
Assert.True(System.Math.Abs(expected - actualRatio) < 0.05f)

0 commit comments

Comments
 (0)