@@ -85,6 +85,30 @@ public TFOutput ReduceMean (TFOutput input, TFOutput? axis = null, bool? keep_di
8585 return this . Mean ( input , this . ReduceDims ( input , axis ) , keep_dims , operName ) ;
8686 }
8787
88+ // Helper method to create a variable and track it.
89+ Variable MakeVariable ( TFOutput initialValue , bool trainable , string operName )
90+ {
91+ var scopeName = MakeName ( "Variable" , operName ) ;
92+
93+ using ( var newScope = WithScope ( scopeName ) ) {
94+ var type = initialValue . OutputType ;
95+ var variableHandle = VarHandleOp ( type , new TFShape ( GetShape ( initialValue ) ) ) ;
96+ using ( var aScope = WithScope ( "Assign" ) ) {
97+ var assignOp = AssignVariableOp ( variableHandle , initialValue ) ;
98+ using ( var rScope = WithScope ( "Read" ) ) {
99+ var readHandle = ReadVariableOp ( variableHandle , type ) ;
100+
101+ var nv = new Variable ( variableHandle , readHandle , assignOp ) ;
102+ if ( trainable )
103+ AddTrainableVariable ( nv ) ;
104+ AddInitVariable ( assignOp ) ;
105+ return nv ;
106+ }
107+ }
108+ }
109+
110+ }
111+
88112 /// <summary>
89113 /// Variable node, with a starting initial value.
90114 /// </summary>
@@ -93,32 +117,21 @@ public TFOutput ReduceMean (TFOutput input, TFOutput? axis = null, bool? keep_di
93117 /// <param name="value">Returns the value of the variable.</param>
94118 /// <param name="trainable">If true, this add the variable to the graph's TrainableVariables, this collection is intended to be used by the Optimizer classes.</param>
95119 /// <param name="operName">Operation name, optional.</param>
96- /// <returns>The returning TFOutput returns the handle to the variable.</returns>
120+ /// <returns>The returning Variable contains the variable, with three nodes with the operations making up the variable assignment .</returns>
97121 /// <remarks>
98122 /// Variables need to be initialized before the main execution so you will typically want to
99123 /// run the session on the variable
100124 /// </remarks>
101- public TFOutput Variable ( TFOutput initialValue , out TFOperation init , out TFOutput value , bool trainable = true , string operName = null )
125+ public Variable Variable ( TFOutput initialValue , out TFOperation init , out TFOutput value , bool trainable = true , string operName = null )
102126 {
103- var scopeName = MakeName ( "Variable" , operName ) ;
104-
105- using ( var newScope = WithScope ( scopeName ) ) {
106- var type = initialValue . OutputType ;
107- var handle = VarHandleOp ( type , new TFShape ( GetShape ( initialValue ) ) ) ;
108- using ( var aScope = WithScope ( "Assign" ) ) {
109- init = AssignVariableOp ( handle , initialValue ) ;
110- if ( trainable )
111- AddTrainableVariable ( handle . Operation ) ;
112- using ( var rScope = WithScope ( "Read" ) ) {
113- value = ReadVariableOp ( handle , type ) ;
114- return handle ;
115- }
116- }
117- }
127+ var nv = MakeVariable ( initialValue , trainable , operName ) ;
128+ init = nv . Assign ;
129+ value = nv . Read ;
130+ return nv ;
118131 }
119132
120133 List < TFOperation > pending_init_variables ;
121- List < TFOperation > trainable_variables ;
134+ List < Variable > trainable_variables ;
122135
123136 /// <summary>
124137 /// Registers a specified variable as an initialization variable.
@@ -144,10 +157,10 @@ public void AddInitVariable (TFOperation variable)
144157 }
145158
146159 // TODO: finalize semantics, when should we clear these?
147- internal void AddTrainableVariable ( TFOperation variable )
160+ internal void AddTrainableVariable ( Variable variable )
148161 {
149162 if ( trainable_variables == null )
150- trainable_variables = new List < TFOperation > ( ) ;
163+ trainable_variables = new List < Variable > ( ) ;
151164 trainable_variables . Add ( variable ) ;
152165 }
153166
@@ -173,32 +186,19 @@ public TFOperation [] GetGlobalVariablesInitializer ()
173186 /// <param name="value">Returns the value of the variable.</param>
174187 /// <param name="trainable">If true, this add the variable to the graph's TrainableVariables, this collection is intended to be used by the Optimizer classes.</param>
175188 /// <param name="operName">Operation name, optional.</param>
176- /// <returns>The returning TFOutput returns the handle to the variable.</returns>
189+ /// <returns>The returning Variable contains the variable, with three nodes with the operations making up the variable assignment .</returns>
177190 /// <remarks>
178191 /// Variables need to be initialized before the main execution so you will typically want to
179192 /// run the session on the variable.
180193 ///
181194 /// The init sequence for the variable is stored in the graph, you must manually initialize
182195 /// those by running the session on the global variables.
183196 /// </remarks>
184- public TFOutput Variable ( TFOutput initialValue , out TFOutput value , bool trainable = true , string operName = null )
197+ public Variable Variable ( TFOutput initialValue , out TFOutput value , bool trainable = true , string operName = null )
185198 {
186- var scopeName = MakeName ( "Variable" , operName ) ;
187-
188- using ( var newScope = WithScope ( scopeName ) ) {
189- var type = initialValue . OutputType ;
190- var handle = VarHandleOp ( type , new TFShape ( GetShape ( initialValue ) ) ) ;
191- using ( var aScope = WithScope ( "Assign" ) ) {
192- var init = AssignVariableOp ( handle , initialValue ) ;
193- AddInitVariable ( init ) ;
194- if ( trainable )
195- AddTrainableVariable ( handle . Operation ) ;
196- using ( var rScope = WithScope ( "Read" ) ) {
197- value = ReadVariableOp ( handle , type ) ;
198- return handle ;
199- }
200- }
201- }
199+ var nv = MakeVariable ( initialValue , trainable , operName ) ;
200+ value = nv . Read ;
201+ return nv ;
202202 }
203203
204204 /// <summary>
@@ -207,29 +207,17 @@ public TFOutput Variable (TFOutput initialValue, out TFOutput value, bool traina
207207 /// <param name="initialValue">Initial value.</param>
208208 /// <param name="trainable">If true, this add the variable to the graph's TrainableVariables, this collection is intended to be used by the Optimizer classes.</param>
209209 /// <param name="operName">Operation name, optional.</param>
210- /// <returns>The returning TFOutput returns the handle to the variable, this is a VarHandleOp, if you want to read it, create a ReadVariableOp on result .</returns>
210+ /// <returns>The returning Variable contains the variable, with three nodes with the operations making up the variable assignment .</returns>
211211 /// <remarks>
212212 /// Variables need to be initialized before the main execution so you will typically want to
213213 /// run the session on the variable.
214214 ///
215215 /// The init sequence for the variable is stored in the graph, you must manually initialize
216216 /// those by running the session on the global variables.
217217 /// </remarks>
218- public TFOutput Variable ( TFOutput initialValue , bool trainable = true , string operName = null )
218+ public Variable Variable ( TFOutput initialValue , bool trainable = true , string operName = null )
219219 {
220- var scopeName = MakeName ( "Variable" , operName ) ;
221- using ( var newScope = WithScope ( scopeName ) ) {
222- var type = initialValue . OutputType ;
223-
224- var handle = VarHandleOp ( type , new TFShape ( GetShape ( initialValue ) ) ) ;
225- using ( var aScope = WithScope ( "Assign" ) ) {
226- var init = AssignVariableOp ( handle , initialValue ) ;
227- AddInitVariable ( init ) ;
228- if ( trainable )
229- AddTrainableVariable ( handle . Operation ) ;
230- return handle ;
231- }
232- }
220+ return MakeVariable ( initialValue , trainable , operName ) ;
233221 }
234222
235223 //
0 commit comments