Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 1.9k
Enable TensorFlowTransform to work with pre-trained models that are not frozen#853
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
100795540fbedc48d14c635ff43a6291d0d57508d3cfcd70f236de73781cff007b15a047f75b5c304257d0430b5950a21097eb497173729f292140b655a8aabe5285a46c04a3e705f9384214e204d02b889693bd8c8d92ed8edc64eea524eb609ffd74b88993382a83aa8e84425b1e64e32accaac45539ce4efef8b8764bf9554886e11f2ced715137df343df883d78ae672d6fac8dae2b1a57621879f6a1d912df6a1c845957c535120bb9a624a3b8d9fdc5685ab992d0ec1e8d8b986File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2,15 +2,17 @@ | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
| // See the LICENSE file in the project root for more information. | ||
| using Microsoft.ML.Runtime; | ||
| using Microsoft.ML.Runtime.Data; | ||
| using Microsoft.ML.Runtime.ImageAnalytics.EntryPoints; | ||
| using Microsoft.ML.Runtime.Internal.Utilities; | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using System.Linq; | ||
| using System.Runtime.InteropServices; | ||
| using Microsoft.ML.Runtime; | ||
| using Microsoft.ML.Runtime.Data; | ||
| using Microsoft.ML.Runtime.ImageAnalytics.EntryPoints; | ||
| using Microsoft.ML.Runtime.Internal.Utilities; | ||
| using System.Security.AccessControl; | ||
| using System.Security.Principal; | ||
| namespace Microsoft.ML.Transforms.TensorFlow | ||
| { | ||
| @@ -158,6 +160,152 @@ internal static TFSession LoadTFSession(IExceptionContext ectx, byte[] modelByte | ||
| return new TFSession(graph); | ||
| } | ||
| private static TFSession LoadTFSession(IHostEnvironment env, string exportDirSavedModel) | ||
| { | ||
| Contracts.Check(env != null, nameof(env)); | ||
| env.CheckValue(exportDirSavedModel, nameof(exportDirSavedModel)); | ||
| var sessionOptions = new TFSessionOptions(); | ||
| var tags = new string[] { "serve" }; | ||
| var graph = new TFGraph(); | ||
| var metaGraphDef = new TFBuffer(); | ||
| return TFSession.FromSavedModel(sessionOptions, null, exportDirSavedModel, tags, graph, metaGraphDef); | ||
| } | ||
| // A TensorFlow frozen model is a single file. An un-frozen (SavedModel) on the other hand has a well-defined folder structure. | ||
| // Given a modelPath, this utility method determines if we should treat it as a SavedModel or not | ||
| internal static bool IsSavedModel(IHostEnvironment env, string modelPath) | ||
| { | ||
| Contracts.Check(env != null, nameof(env)); | ||
| env.CheckNonWhiteSpace(modelPath, nameof(modelPath)); | ||
| FileAttributes attr = File.GetAttributes(modelPath); | ||
| return attr.HasFlag(FileAttributes.Directory); | ||
| } | ||
| // Currently used in TensorFlowTransform to protect temporary folders used when working with TensorFlow's SavedModel format. | ||
| // Models are considered executable code, so we need to ACL tthe temp folders for high-rights process (so low-rights process can’t access it). | ||
| /// <summary> | ||
| /// Given a folder path, create it with proper ACL if it doesn't exist. | ||
| /// Fails if the folder name is empty, or can't create the folder. | ||
| /// </summary> | ||
| internal static void CreateFolderWithAclIfNotExists(IHostEnvironment env, string folder) | ||
| ||
| { | ||
| Contracts.Check(env != null, nameof(env)); | ||
| env.CheckNonWhiteSpace(folder, nameof(folder)); | ||
| //if directory exists, do nothing. | ||
| if (Directory.Exists(folder)) | ||
| return; | ||
| WindowsIdentity currentIdentity = null; | ||
| try | ||
| { | ||
| currentIdentity = WindowsIdentity.GetCurrent(); | ||
| } | ||
| catch (PlatformNotSupportedException) | ||
| { } | ||
| if (currentIdentity != null && new WindowsPrincipal(currentIdentity).IsInRole(WindowsBuiltInRole.Administrator)) | ||
| { | ||
| // Create high integrity dir and set no delete policy for all files under the directory. | ||
| // In case of failure, throw exception. | ||
| CreateTempDirectoryWithAcl(folder, currentIdentity.User.ToString()); | ||
| } | ||
| else | ||
| { | ||
| try | ||
| { | ||
| Directory.CreateDirectory(folder); | ||
| } | ||
| catch (Exception exc) | ||
| { | ||
| throw Contracts.ExceptParam(nameof(folder), $"Failed to create folder for the provided path: {folder}. \nException: {exc.Message}"); | ||
| } | ||
| } | ||
| } | ||
| internal static void DeleteFolderWithRetries(IHostEnvironment env, string folder) | ||
| { | ||
| Contracts.Check(env != null, nameof(env)); | ||
| int currentRetry = 0; | ||
| int maxRetryCount = 10; | ||
| using (var ch = env.Start("Delete folder")) | ||
| { | ||
| for (; ; ) | ||
| { | ||
| try | ||
| { | ||
| currentRetry++; | ||
| Directory.Delete(folder, true); | ||
| break; | ||
| } | ||
| catch (IOException e) | ||
| { | ||
| if (currentRetry > maxRetryCount) | ||
| throw; | ||
| ch.Info("Error deleting folder. {0}. Retry,", e.Message); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| private static void CreateTempDirectoryWithAcl(string folder, string identity) | ||
| { | ||
| // Dacl Sddl string: | ||
| // D: Dacl type | ||
| // D; Deny access | ||
| // OI; Object inherit ace | ||
| // SD; Standard delete function | ||
| // wIdentity.User Sid of the given user. | ||
| // A; Allow access | ||
| // OICI; Object inherit, container inherit | ||
| // FA File access | ||
| // BA Built-in administrators | ||
| // S: Sacl type | ||
| // ML;; Mandatory Label | ||
| // NW;;; No write policy | ||
| // HI High integrity processes only | ||
| string sddl = "D:(D;OI;SD;;;" + identity + ")(A;OICI;FA;;;BA)S:(ML;OI;NW;;;HI)"; | ||
| try | ||
| { | ||
| var dir = Directory.CreateDirectory(folder); | ||
| DirectorySecurity dirSec = new DirectorySecurity(); | ||
| dirSec.SetSecurityDescriptorSddlForm(sddl); | ||
| dirSec.SetAccessRuleProtection(true, false); // disable inheritance | ||
| dir.SetAccessControl(dirSec); | ||
| // Cleaning out the directory, in case someone managed to sneak in between creation and setting ACL. | ||
| DirectoryInfo dirInfo = new DirectoryInfo(folder); | ||
| foreach (FileInfo file in dirInfo.GetFiles()) | ||
| { | ||
| file.Delete(); | ||
| } | ||
| foreach (DirectoryInfo subDirInfo in dirInfo.GetDirectories()) | ||
| { | ||
| subDirInfo.Delete(true); | ||
| } | ||
| } | ||
| catch (Exception exc) | ||
| { | ||
| throw Contracts.ExceptParam(nameof(folder), $"Failed to create folder for the provided path: {folder}. \nException: {exc.Message}"); | ||
| } | ||
| } | ||
| internal static TFSession GetSession(IHostEnvironment env, string modelPath) | ||
| { | ||
| ||
| Contracts.Check(env != null, nameof(env)); | ||
| if (IsSavedModel(env, modelPath)) | ||
| { | ||
| env.CheckUserArg(Directory.Exists(modelPath), nameof(modelPath)); | ||
| return LoadTFSession(env, modelPath); | ||
| } | ||
| env.CheckUserArg(File.Exists(modelPath), nameof(modelPath)); | ||
| var bytes = File.ReadAllBytes(modelPath); | ||
| return LoadTFSession(env, bytes, modelPath); | ||
| } | ||
| internal static unsafe void FetchData<T>(IntPtr data, T[] result) | ||
| { | ||
| var size = result.Length; | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be
netcoreapp2.1. Note thatnetcoreappandnetstandardare different things. We wantnetcoreapp2.1for any and all executables and tests. We wantnetstandard2.0for any libraries.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moreover, we don't even want this in the lib folder as it is just a commandline tool.