| @@ -5,14 +5,8 @@ VisualStudioVersion = 16.0.29102.190 | |||||
| MinimumVisualStudioVersion = 10.0.40219.1 | MinimumVisualStudioVersion = 10.0.40219.1 | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.UnitTest", "test\TensorFlowNET.UnitTest\TensorFlowNET.UnitTest.csproj", "{029A8CF1-CF95-4DCB-98AA-9D3D96A83B3E}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.UnitTest", "test\TensorFlowNET.UnitTest\TensorFlowNET.UnitTest.csproj", "{029A8CF1-CF95-4DCB-98AA-9D3D96A83B3E}" | ||||
| EndProject | EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.Examples", "test\TensorFlowNET.Examples\TensorFlowNET.Examples.csproj", "{1FE60088-157C-4140-91AB-E96B915E4BAE}" | |||||
| EndProject | |||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.Core", "src\TensorFlowNET.Core\TensorFlowNET.Core.csproj", "{FD682AC0-7B2D-45D3-8B0D-C6D678B04144}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.Core", "src\TensorFlowNET.Core\TensorFlowNET.Core.csproj", "{FD682AC0-7B2D-45D3-8B0D-C6D678B04144}" | ||||
| EndProject | EndProject | ||||
| Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "TensorFlowNET.Examples.FSharp", "test\TensorFlowNET.Examples.FSharp\TensorFlowNET.Examples.FSharp.fsproj", "{62BC3801-F0D3-44A9-A0AC-712F40C8F961}" | |||||
| EndProject | |||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowBenchmark", "src\TensorFlowNet.Benchmarks\TensorFlowBenchmark.csproj", "{68861442-971A-4196-876E-C9330F0B3C54}" | |||||
| EndProject | |||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowHub", "src\TensorFlowHub\TensorFlowHub.csproj", "{8FD59A5A-97EB-457E-B9F1-D88B0C822C6E}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowHub", "src\TensorFlowHub\TensorFlowHub.csproj", "{8FD59A5A-97EB-457E-B9F1-D88B0C822C6E}" | ||||
| EndProject | EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowText", "src\TensorFlowText\TensorFlowText.csproj", "{B598E5D5-BD2D-4191-8532-F2FBAC31AB81}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowText", "src\TensorFlowText\TensorFlowText.csproj", "{B598E5D5-BD2D-4191-8532-F2FBAC31AB81}" | ||||
| @@ -31,22 +25,10 @@ Global | |||||
| {029A8CF1-CF95-4DCB-98AA-9D3D96A83B3E}.Debug|Any CPU.Build.0 = Debug|Any CPU | {029A8CF1-CF95-4DCB-98AA-9D3D96A83B3E}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| {029A8CF1-CF95-4DCB-98AA-9D3D96A83B3E}.Release|Any CPU.ActiveCfg = Release|Any CPU | {029A8CF1-CF95-4DCB-98AA-9D3D96A83B3E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {029A8CF1-CF95-4DCB-98AA-9D3D96A83B3E}.Release|Any CPU.Build.0 = Release|Any CPU | {029A8CF1-CF95-4DCB-98AA-9D3D96A83B3E}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {1FE60088-157C-4140-91AB-E96B915E4BAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {1FE60088-157C-4140-91AB-E96B915E4BAE}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
| {1FE60088-157C-4140-91AB-E96B915E4BAE}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {1FE60088-157C-4140-91AB-E96B915E4BAE}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|Any CPU.Build.0 = Debug|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Release|Any CPU.ActiveCfg = Release|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Release|Any CPU.Build.0 = Release|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {62BC3801-F0D3-44A9-A0AC-712F40C8F961}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {62BC3801-F0D3-44A9-A0AC-712F40C8F961}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
| {62BC3801-F0D3-44A9-A0AC-712F40C8F961}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {62BC3801-F0D3-44A9-A0AC-712F40C8F961}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
| {68861442-971A-4196-876E-C9330F0B3C54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {68861442-971A-4196-876E-C9330F0B3C54}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
| {68861442-971A-4196-876E-C9330F0B3C54}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {68861442-971A-4196-876E-C9330F0B3C54}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
| {8FD59A5A-97EB-457E-B9F1-D88B0C822C6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | {8FD59A5A-97EB-457E-B9F1-D88B0C822C6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| {8FD59A5A-97EB-457E-B9F1-D88B0C822C6E}.Debug|Any CPU.Build.0 = Debug|Any CPU | {8FD59A5A-97EB-457E-B9F1-D88B0C822C6E}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| {8FD59A5A-97EB-457E-B9F1-D88B0C822C6E}.Release|Any CPU.ActiveCfg = Release|Any CPU | {8FD59A5A-97EB-457E-B9F1-D88B0C822C6E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| @@ -1,45 +0,0 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Threading.Tasks; | |||||
| using Microsoft.AspNetCore.Mvc; | |||||
| namespace TensorFlowNET.Visualization.Controllers | |||||
| { | |||||
| [Route("api/[controller]")] | |||||
| [ApiController] | |||||
| public class ValuesController : ControllerBase | |||||
| { | |||||
| // GET api/values | |||||
| [HttpGet] | |||||
| public ActionResult<IEnumerable<string>> Get() | |||||
| { | |||||
| return new string[] { "value1", "value2" }; | |||||
| } | |||||
| // GET api/values/5 | |||||
| [HttpGet("{id}")] | |||||
| public ActionResult<string> Get(int id) | |||||
| { | |||||
| return "value"; | |||||
| } | |||||
| // POST api/values | |||||
| [HttpPost] | |||||
| public void Post([FromBody] string value) | |||||
| { | |||||
| } | |||||
| // PUT api/values/5 | |||||
| [HttpPut("{id}")] | |||||
| public void Put(int id, [FromBody] string value) | |||||
| { | |||||
| } | |||||
| // DELETE api/values/5 | |||||
| [HttpDelete("{id}")] | |||||
| public void Delete(int id) | |||||
| { | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,24 +0,0 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using System.Threading.Tasks; | |||||
| using Microsoft.AspNetCore; | |||||
| using Microsoft.AspNetCore.Hosting; | |||||
| using Microsoft.Extensions.Configuration; | |||||
| using Microsoft.Extensions.Logging; | |||||
| namespace TensorFlowNET.Visualization | |||||
| { | |||||
| public class Program | |||||
| { | |||||
| public static void Main(string[] args) | |||||
| { | |||||
| CreateWebHostBuilder(args).Build().Run(); | |||||
| } | |||||
| public static IWebHostBuilder CreateWebHostBuilder(string[] args) => | |||||
| WebHost.CreateDefaultBuilder(args) | |||||
| .UseStartup<Startup>(); | |||||
| } | |||||
| } | |||||
| @@ -1,41 +0,0 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Threading.Tasks; | |||||
| using Microsoft.AspNetCore.Builder; | |||||
| using Microsoft.AspNetCore.Hosting; | |||||
| using Microsoft.AspNetCore.Mvc; | |||||
| using Microsoft.Extensions.Configuration; | |||||
| using Microsoft.Extensions.DependencyInjection; | |||||
| using Microsoft.Extensions.Logging; | |||||
| using Microsoft.Extensions.Options; | |||||
| namespace TensorFlowNET.Visualization | |||||
| { | |||||
| public class Startup | |||||
| { | |||||
| public Startup(IConfiguration configuration) | |||||
| { | |||||
| Configuration = configuration; | |||||
| } | |||||
| public IConfiguration Configuration { get; } | |||||
| // This method gets called by the runtime. Use this method to add services to the container. | |||||
| public void ConfigureServices(IServiceCollection services) | |||||
| { | |||||
| services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); | |||||
| } | |||||
| // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | |||||
| public void Configure(IApplicationBuilder app, IHostingEnvironment env) | |||||
| { | |||||
| if (env.IsDevelopment()) | |||||
| { | |||||
| app.UseDeveloperExceptionPage(); | |||||
| } | |||||
| app.UseMvc(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,17 +0,0 @@ | |||||
| <Project Sdk="Microsoft.NET.Sdk.Web"> | |||||
| <PropertyGroup> | |||||
| <TargetFramework>netcoreapp2.1</TargetFramework> | |||||
| <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel> | |||||
| </PropertyGroup> | |||||
| <ItemGroup> | |||||
| <PackageReference Include="Microsoft.AspNetCore.App" /> | |||||
| <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <ProjectReference Include="..\TensorFlowNET.Core\TensorFlowNET.Core.csproj" /> | |||||
| </ItemGroup> | |||||
| </Project> | |||||
| @@ -1,9 +0,0 @@ | |||||
| { | |||||
| "Logging": { | |||||
| "LogLevel": { | |||||
| "Default": "Debug", | |||||
| "System": "Information", | |||||
| "Microsoft": "Information" | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,8 +0,0 @@ | |||||
| { | |||||
| "Logging": { | |||||
| "LogLevel": { | |||||
| "Default": "Warning" | |||||
| } | |||||
| }, | |||||
| "AllowedHosts": "*" | |||||
| } | |||||
| @@ -1,29 +0,0 @@ | |||||
| using System; | |||||
| using System.Reflection; | |||||
| using BenchmarkDotNet.Configs; | |||||
| using BenchmarkDotNet.Running; | |||||
| namespace TensorFlowBenchmark | |||||
| { | |||||
| class Program | |||||
| { | |||||
| static void Main(string[] args) | |||||
| { | |||||
| if (args?.Length > 0) | |||||
| { | |||||
| for (int i = 0; i < args.Length; i++) | |||||
| { | |||||
| string name = $"TensorFlowBenchmark.{args[i]}"; | |||||
| var type = Type.GetType(name); | |||||
| BenchmarkRunner.Run(type); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| BenchmarkSwitcher.FromAssembly(Assembly.GetExecutingAssembly()).Run(args, ManualConfig.Create(DefaultConfig.Instance).With(ConfigOptions.DisableOptimizationsValidator)); | |||||
| } | |||||
| Console.ReadLine(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,88 +0,0 @@ | |||||
| using System; | |||||
| using BenchmarkDotNet.Attributes; | |||||
| using NumSharp; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowBenchmark | |||||
| { | |||||
| [SimpleJob(launchCount: 1, warmupCount: 2, targetCount: 10)] | |||||
| [MinColumn, MaxColumn, MeanColumn, MedianColumn] | |||||
| public class TensorBenchmark | |||||
| { | |||||
| private double[] data; | |||||
| [GlobalSetup] | |||||
| public void Setup() | |||||
| { | |||||
| data = new double[100]; | |||||
| } | |||||
| [Benchmark] | |||||
| public void ScalarTensor() | |||||
| { | |||||
| var g = new Graph(); | |||||
| for (int i = 0; i < 100; i++) | |||||
| { | |||||
| using (var tensor = new Tensor(17.0)) | |||||
| { | |||||
| } | |||||
| } | |||||
| } | |||||
| [Benchmark] | |||||
| public unsafe void TensorFromFixedPtr() | |||||
| { | |||||
| var g = new Graph(); | |||||
| for (int i = 0; i < 100; i++) | |||||
| { | |||||
| fixed (double* ptr = &data[0]) | |||||
| { | |||||
| using (var t = new Tensor((IntPtr)ptr, new long[] { data.Length }, tf.float64, 8 * data.Length)) | |||||
| { | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| [Benchmark] | |||||
| public void TensorFromArray() | |||||
| { | |||||
| var g=new Graph(); | |||||
| for (int i = 0; i < 100; i++) | |||||
| { | |||||
| using (var tensor = new Tensor(data)) | |||||
| { | |||||
| } | |||||
| } | |||||
| } | |||||
| [Benchmark] | |||||
| public void TensorFromNDArray() | |||||
| { | |||||
| var g = new Graph(); | |||||
| for (int i = 0; i < 1000; i++) | |||||
| { | |||||
| using (var tensor = new Tensor(new NDArray(data))) | |||||
| { | |||||
| } | |||||
| } | |||||
| } | |||||
| //[Benchmark] | |||||
| //public void Constant() | |||||
| //{ | |||||
| // for (int i = 0; i < 100; i++) | |||||
| // { | |||||
| // //var tensor = new Tensor(new NDArray(data)); | |||||
| // var c = tf.constant(42.0); | |||||
| // } | |||||
| //} | |||||
| } | |||||
| } | |||||
| @@ -1,33 +0,0 @@ | |||||
| <Project Sdk="Microsoft.NET.Sdk"> | |||||
| <PropertyGroup> | |||||
| <OutputType>Exe</OutputType> | |||||
| <TargetFramework>netcoreapp3.0</TargetFramework> | |||||
| <NoWin32Manifest>true</NoWin32Manifest> | |||||
| <AssemblyName>TensorFlowBenchmark</AssemblyName> | |||||
| <RootNamespace>TensorFlowBenchmark</RootNamespace> | |||||
| <LangVersion>7.3</LangVersion> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | |||||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | |||||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | |||||
| </PropertyGroup> | |||||
| <ItemGroup> | |||||
| <None Remove="tensorflow.dll" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <PackageReference Include="BenchmarkDotNet" Version="0.11.5" /> | |||||
| <PackageReference Include="SciSharp.TensorFlow.Redist" Version="1.14.0" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <ProjectReference Include="..\TensorFlowNET.Core\TensorFlowNET.Core.csproj" /> | |||||
| </ItemGroup> | |||||
| </Project> | |||||
| @@ -1,20 +0,0 @@ | |||||
| <Project Sdk="Microsoft.NET.Sdk"> | |||||
| <PropertyGroup> | |||||
| <OutputType>Exe</OutputType> | |||||
| <TargetFramework>netcoreapp2.2</TargetFramework> | |||||
| </PropertyGroup> | |||||
| <ItemGroup> | |||||
| <None Remove="tensorflow.dll" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <PackageReference Include="BenchmarkDotNet" Version="0.11.5" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <ProjectReference Include="..\TensorFlowNET.Core\TensorFlowNET.Core.csproj" /> | |||||
| </ItemGroup> | |||||
| </Project> | |||||
| @@ -1,76 +0,0 @@ | |||||
| using System; | |||||
| using System.Runtime.CompilerServices; | |||||
| using System.Runtime.InteropServices; | |||||
| using BenchmarkDotNet.Attributes; | |||||
| using Google.Protobuf.WellKnownTypes; | |||||
| using NumSharp; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowBenchmark.Unmanaged | |||||
| { | |||||
| public struct UnmanagedStruct | |||||
| { | |||||
| public int a; | |||||
| public long b; | |||||
| public UnmanagedStruct(int _) | |||||
| { | |||||
| a = 2; | |||||
| b = 3; | |||||
| } | |||||
| } | |||||
| [SimpleJob(launchCount: 1, warmupCount: 2, targetCount: 10)] | |||||
| [MinColumn, MaxColumn, MeanColumn, MedianColumn] | |||||
| public unsafe class StructCastBenchmark | |||||
| { | |||||
| private static void EnsureIsUnmanaged<T>(T _) where T : unmanaged | |||||
| { } | |||||
| static StructCastBenchmark() //if UnmanagedStruct is not unmanaged struct then this will fail to compile. | |||||
| => EnsureIsUnmanaged(new UnmanagedStruct()); | |||||
| private IntPtr data; | |||||
| private void* dataptr; | |||||
| [GlobalSetup] | |||||
| public void Setup() | |||||
| { | |||||
| data = Marshal.AllocHGlobal(Marshal.SizeOf<UnmanagedStruct>()); | |||||
| dataptr = data.ToPointer(); | |||||
| } | |||||
| [Benchmark, MethodImpl(MethodImplOptions.NoOptimization)] | |||||
| public void Marshal_PtrToStructure() | |||||
| { | |||||
| UnmanagedStruct _; | |||||
| for (int i = 0; i < 10000; i++) | |||||
| { | |||||
| _ = Marshal.PtrToStructure<UnmanagedStruct>(data); | |||||
| } | |||||
| } | |||||
| [Benchmark, MethodImpl(MethodImplOptions.NoOptimization)] | |||||
| public void PointerCast() | |||||
| { | |||||
| var dptr = dataptr; | |||||
| UnmanagedStruct _; | |||||
| for (int i = 0; i < 10000; i++) | |||||
| { | |||||
| _ = *(UnmanagedStruct*) dptr; | |||||
| } | |||||
| } | |||||
| [Benchmark, MethodImpl(MethodImplOptions.NoOptimization)] | |||||
| public void Unsafe_Read() | |||||
| { | |||||
| var dptr = dataptr; | |||||
| UnmanagedStruct _; | |||||
| for (int i = 0; i < 10000; i++) | |||||
| { | |||||
| _ = Unsafe.Read<UnmanagedStruct>(dptr); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,104 +0,0 @@ | |||||
| module FunctionApproximation | |||||
| //reduced example from https://github.com/tirthajyoti/Machine-Learning-with-Python/blob/master/Function%20Approximation%20by%20Neural%20Network/Function%20approximation%20by%20linear%20model%20and%20deep%20network.ipynb | |||||
| open NumSharp | |||||
| open Tensorflow | |||||
| open System | |||||
| let run()= | |||||
| let N_points = 75 // Number of points for constructing function | |||||
| let x_min = 1.0 // Min of the range of x (feature) | |||||
| let x_max = 15.0 // Max of the range of x (feature) | |||||
| let noise_mean = 0.0 // Mean of the Gaussian noise adder | |||||
| let noise_sd = 10.0 // Std.Dev of the Gaussian noise adder | |||||
| let linspace points = [| for i in 0 .. (points - 1) -> x_min + (x_max - x_min)/(float)points * (float)i |] | |||||
| let func_trans(xAr:float []) = | |||||
| xAr | |||||
| |>Array.map (fun (x:float) -> (20.0 * x+3.0 * System.Math.Pow(x,2.0)+0.1 * System.Math.Pow(x,3.0))*sin(x)*exp(-0.1*x)) | |||||
| let X_raw = linspace N_points | |||||
| let Y_raw = func_trans(X_raw) | |||||
| let X_mtr = Array2D.init X_raw.Length 1 (fun i j -> X_raw.[i]) | |||||
| let X = np.array(X_mtr) | |||||
| let noise_x = np.random.normal(noise_mean,noise_sd,N_points) | |||||
| let y = np.array(Y_raw)+noise_x | |||||
| let X_train = X | |||||
| let y_train = y | |||||
| let learning_rate = 0.00001 | |||||
| let training_epochs = 35000 | |||||
| let n_input = 1 // Number of features | |||||
| let n_output = 1 // Regression output is a number only | |||||
| let n_hidden_layer_1 = 25 // Hidden layer 1 | |||||
| let n_hidden_layer_2 = 25 // Hidden layer 2 | |||||
| let tf = Binding.New<tensorflow>() | |||||
| let x = tf.placeholder(tf.float64, new TensorShape(N_points,n_input)) | |||||
| let y = tf.placeholder(tf.float64, new TensorShape(n_output)) | |||||
| let weights = dict[ | |||||
| "hidden_layer_1", tf.Variable(tf.random_normal([|n_input; n_hidden_layer_1|],dtype=tf.float64)) | |||||
| "hidden_layer_2", tf.Variable(tf.random_normal([|n_hidden_layer_1; n_hidden_layer_2|],dtype=tf.float64)) | |||||
| "out", tf.Variable(tf.random_normal([|n_hidden_layer_2; n_output|],dtype=tf.float64)) | |||||
| ] | |||||
| let biases = dict[ | |||||
| "hidden_layer_1", tf.Variable(tf.random_normal([|n_hidden_layer_1|],dtype=tf.float64)) | |||||
| "hidden_layer_2", tf.Variable(tf.random_normal([|n_hidden_layer_2|],dtype=tf.float64)) | |||||
| "out", tf.Variable(tf.random_normal([|n_output|],dtype=tf.float64)) | |||||
| ] | |||||
| // Hidden layer with RELU activation | |||||
| let layer_1 = tf.add(tf.matmul(x, weights.["hidden_layer_1"]._AsTensor()),biases.["hidden_layer_1"]) | |||||
| let layer_1 = tf.nn.relu(layer_1) | |||||
| let layer_2 = tf.add(tf.matmul(layer_1, weights.["hidden_layer_2"]._AsTensor()),biases.["hidden_layer_2"]) | |||||
| let layer_2 = tf.nn.relu(layer_2) | |||||
| // Output layer with linear activation | |||||
| let ops = tf.add(tf.matmul(layer_2, weights.["out"]._AsTensor()), biases.["out"]) | |||||
| // Define loss and optimizer | |||||
| let cost = tf.reduce_mean(tf.square(tf.squeeze(ops)-y)) | |||||
| let gs = tf.Variable(1, trainable= false, name= "global_step") | |||||
| let optimizer = tf.train.GradientDescentOptimizer(learning_rate=(float32)learning_rate).minimize(cost,global_step = gs) | |||||
| let init = tf.global_variables_initializer() | |||||
| Tensorflow.Binding.``tf_with``(tf.Session(), fun (sess:Session) -> | |||||
| sess.run(init) |> ignore | |||||
| // Loop over epochs | |||||
| for epoch in [0..training_epochs] do | |||||
| // Run optimization process (backprop) and cost function (to get loss value) | |||||
| let result=sess.run([|optimizer:>ITensorOrOperation; gs._AsTensor():>ITensorOrOperation; cost:>ITensorOrOperation|], new FeedItem(x, X_train), new FeedItem(y, y_train)) | |||||
| let loss_value = (double) result.[2]; | |||||
| let step = (int) result.[1]; | |||||
| if epoch % 1000 = 0 then | |||||
| sprintf "Step %d loss: %f" step loss_value |> Console.WriteLine | |||||
| let w=sess.run(weights |> Array.ofSeq |> Array.map (fun pair -> pair.Value)) | |||||
| let b = sess.run(biases |> Array.ofSeq |> Array.map (fun pair -> pair.Value)) | |||||
| let yhat=sess.run([|ops:>ITensorOrOperation|],new FeedItem(x,X_train)) | |||||
| for i in [0..(N_points-1)] do | |||||
| sprintf "pred %f real: %f" ((double)(yhat.[0].[i].[0])) ((double)Y_raw.[i]) |> Console.WriteLine | |||||
| ) | |||||
| @@ -1,8 +0,0 @@ | |||||
| // Learn more about F# at http://fsharp.org | |||||
| open System | |||||
| [<EntryPoint>] | |||||
| let main argv = | |||||
| FunctionApproximation.run() | |||||
| 0 // return an integer exit code | |||||
| @@ -1,21 +0,0 @@ | |||||
| <Project Sdk="Microsoft.NET.Sdk"> | |||||
| <PropertyGroup> | |||||
| <OutputType>Exe</OutputType> | |||||
| <TargetFramework>netcoreapp2.2</TargetFramework> | |||||
| </PropertyGroup> | |||||
| <ItemGroup> | |||||
| <Compile Include="FunctionApproximation.fs" /> | |||||
| <Compile Include="Program.fs" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <PackageReference Include="SciSharp.TensorFlow.Redist" Version="1.14.0" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <ProjectReference Include="..\..\src\TensorFlowNET.Core\TensorFlowNET.Core.csproj" /> | |||||
| </ItemGroup> | |||||
| </Project> | |||||
| @@ -1 +0,0 @@ | |||||
| | |||||
| @@ -1,73 +0,0 @@ | |||||
| using System; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Basic introduction to TensorFlow's Eager API. | |||||
| /// https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/1_Introduction/basic_eager_api.py | |||||
| /// </summary> | |||||
| public class BasicEagerApi : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = false; | |||||
| public string Name => "Basic Eager"; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| private Tensor a, b, c, d; | |||||
| public bool Run() | |||||
| { | |||||
| // Set Eager API | |||||
| Console.WriteLine("Setting Eager mode..."); | |||||
| tf.enable_eager_execution(); | |||||
| // Define constant tensors | |||||
| Console.WriteLine("Define constant tensors"); | |||||
| a = tf.constant(2); | |||||
| Console.WriteLine($"a = {a}"); | |||||
| b = tf.constant(3); | |||||
| Console.WriteLine($"b = {b}"); | |||||
| // Run the operation without the need for tf.Session | |||||
| Console.WriteLine("Running operations, without tf.Session"); | |||||
| c = a + b; | |||||
| Console.WriteLine($"a + b = {c}"); | |||||
| d = a * b; | |||||
| Console.WriteLine($"a * b = {d}"); | |||||
| // Full compatibility with Numpy | |||||
| return true; | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,185 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Diagnostics; | |||||
| using Tensorflow; | |||||
| using Tensorflow.Hub; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Implement K-Means algorithm with TensorFlow.NET, and apply it to classify | |||||
| /// handwritten digit images. | |||||
| /// https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/2_BasicModels/kmeans.py | |||||
| /// </summary> | |||||
| public class KMeansClustering : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = false; | |||||
| public string Name => "K-means Clustering"; | |||||
| public bool IsImportingGraph { get; set; } = true; | |||||
| public int? train_size = null; | |||||
| public int validation_size = 5000; | |||||
| public int? test_size = null; | |||||
| public int batch_size = 1024; // The number of samples per batch | |||||
| Datasets<MnistDataSet> mnist; | |||||
| NDArray full_data_x; | |||||
| int num_steps = 20; // Total steps to train | |||||
| int k = 25; // The number of clusters | |||||
| int num_classes = 10; // The 10 digits | |||||
| int num_features = 784; // Each image is 28x28 pixels | |||||
| float accuray_test = 0f; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| var graph = ImportGraph(); | |||||
| using (var sess = tf.Session(graph)) | |||||
| { | |||||
| Train(sess); | |||||
| } | |||||
| return accuray_test > 0.70; | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| var loader = new MnistModelLoader(); | |||||
| var setting = new ModelLoadSetting | |||||
| { | |||||
| TrainDir = ".resources/mnist", | |||||
| OneHot = true, | |||||
| TrainSize = train_size, | |||||
| ValidationSize = validation_size, | |||||
| TestSize = test_size, | |||||
| ShowProgressInConsole = true | |||||
| }; | |||||
| mnist = loader.LoadAsync(setting).Result; | |||||
| full_data_x = mnist.Train.Data; | |||||
| // download graph meta data | |||||
| string url = "https://raw.githubusercontent.com/SciSharp/TensorFlow.NET/master/graph/kmeans.meta"; | |||||
| loader.DownloadAsync(url, ".resources/graph", "kmeans.meta").Wait(); | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| var graph = tf.Graph().as_default(); | |||||
| tf.train.import_meta_graph(".resources/graph/kmeans.meta"); | |||||
| return graph; | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| var graph = tf.Graph(); | |||||
| // Input images | |||||
| Tensor X = graph.get_operation_by_name("Placeholder"); // tf.placeholder(tf.float32, shape: new TensorShape(-1, num_features)); | |||||
| // Labels (for assigning a label to a centroid and testing) | |||||
| Tensor Y = graph.get_operation_by_name("Placeholder_1"); // tf.placeholder(tf.float32, shape: new TensorShape(-1, num_classes)); | |||||
| // K-Means Parameters | |||||
| //var kmeans = new KMeans(X, k, distance_metric: KMeans.COSINE_DISTANCE, use_mini_batch: true); | |||||
| // Build KMeans graph | |||||
| //var training_graph = kmeans.training_graph(); | |||||
| var init_vars = tf.global_variables_initializer(); | |||||
| Tensor init_op = graph.get_operation_by_name("cond/Merge"); | |||||
| var train_op = graph.get_operation_by_name("group_deps"); | |||||
| Tensor avg_distance = graph.get_operation_by_name("Mean"); | |||||
| Tensor cluster_idx = graph.get_operation_by_name("Squeeze_1"); | |||||
| NDArray result = null; | |||||
| sess.run(init_vars, new FeedItem(X, full_data_x)); | |||||
| sess.run(init_op, new FeedItem(X, full_data_x)); | |||||
| // Training | |||||
| var sw = new Stopwatch(); | |||||
| foreach (var i in range(1, num_steps + 1)) | |||||
| { | |||||
| sw.Restart(); | |||||
| result = sess.run(new ITensorOrOperation[] { train_op, avg_distance, cluster_idx }, new FeedItem(X, full_data_x)); | |||||
| sw.Stop(); | |||||
| if (i % 4 == 0 || i == 1) | |||||
| print($"Step {i}, Avg Distance: {result[1]} Elapse: {sw.ElapsedMilliseconds}ms"); | |||||
| } | |||||
| var idx = result[2].Data<int>(); | |||||
| // Assign a label to each centroid | |||||
| // Count total number of labels per centroid, using the label of each training | |||||
| // sample to their closest centroid (given by 'idx') | |||||
| var counts = np.zeros((k, num_classes), np.float32); | |||||
| sw.Start(); | |||||
| foreach (var i in range(idx.Count)) | |||||
| { | |||||
| var x = mnist.Train.Labels[i]; | |||||
| counts[idx[i]] += x; | |||||
| } | |||||
| sw.Stop(); | |||||
| print($"Assign a label to each centroid took {sw.ElapsedMilliseconds}ms"); | |||||
| // Assign the most frequent label to the centroid | |||||
| var labels_map_array = np.argmax(counts, 1); | |||||
| var labels_map = tf.convert_to_tensor(labels_map_array); | |||||
| // Evaluation ops | |||||
| // Lookup: centroid_id -> label | |||||
| var cluster_label = tf.nn.embedding_lookup(labels_map, cluster_idx); | |||||
| // Compute accuracy | |||||
| var correct_prediction = tf.equal(cluster_label, tf.cast(tf.argmax(Y, 1), tf.int32)); | |||||
| var cast = tf.cast(correct_prediction, tf.float32); | |||||
| var accuracy_op = tf.reduce_mean(cast); | |||||
| // Test Model | |||||
| var (test_x, test_y) = (mnist.Test.Data, mnist.Test.Labels); | |||||
| result = sess.run(accuracy_op, new FeedItem(X, test_x), new FeedItem(Y, test_y)); | |||||
| accuray_test = result; | |||||
| print($"Test Accuracy: {accuray_test}"); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,145 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// A linear regression learning algorithm example using TensorFlow library. | |||||
| /// https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/2_BasicModels/linear_regression.py | |||||
| /// </summary> | |||||
| public class LinearRegression : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public string Name => "Linear Regression"; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public int training_epochs = 1000; | |||||
| // Parameters | |||||
| float learning_rate = 0.01f; | |||||
| int display_step = 50; | |||||
| NumPyRandom rng = np.random; | |||||
| NDArray train_X, train_Y; | |||||
| int n_samples; | |||||
| public bool Run() | |||||
| { | |||||
| // Training Data | |||||
| PrepareData(); | |||||
| // tf Graph Input | |||||
| var X = tf.placeholder(tf.float32); | |||||
| var Y = tf.placeholder(tf.float32); | |||||
| // Set model weights | |||||
| // We can set a fixed init value in order to debug | |||||
| // var rnd1 = rng.randn<float>(); | |||||
| // var rnd2 = rng.randn<float>(); | |||||
| var W = tf.Variable(-0.06f, name: "weight"); | |||||
| var b = tf.Variable(-0.73f, name: "bias"); | |||||
| // Construct a linear model | |||||
| var pred = tf.add(tf.multiply(X, W), b); | |||||
| // Mean squared error | |||||
| var cost = tf.reduce_sum(tf.pow(pred - Y, 2.0f)) / (2.0f * n_samples); | |||||
| // Gradient descent | |||||
| // Note, minimize() knows to modify W and b because Variable objects are trainable=True by default | |||||
| var optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost); | |||||
| // Initialize the variables (i.e. assign their default value) | |||||
| var init = tf.global_variables_initializer(); | |||||
| // Start training | |||||
| using (var sess = tf.Session()) | |||||
| { | |||||
| // Run the initializer | |||||
| sess.run(init); | |||||
| // Fit all training data | |||||
| for (int epoch = 0; epoch < training_epochs; epoch++) | |||||
| { | |||||
| foreach (var (x, y) in zip<float>(train_X, train_Y)) | |||||
| sess.run(optimizer, (X, x), (Y, y)); | |||||
| // Display logs per epoch step | |||||
| if ((epoch + 1) % display_step == 0) | |||||
| { | |||||
| var c = sess.run(cost, (X, train_X), (Y, train_Y)); | |||||
| Console.WriteLine($"Epoch: {epoch + 1} cost={c} " + $"W={sess.run(W)} b={sess.run(b)}"); | |||||
| } | |||||
| } | |||||
| Console.WriteLine("Optimization Finished!"); | |||||
| var training_cost = sess.run(cost, (X, train_X), (Y, train_Y)); | |||||
| Console.WriteLine($"Training cost={training_cost} W={sess.run(W)} b={sess.run(b)}"); | |||||
| // Testing example | |||||
| var test_X = np.array(6.83f, 4.668f, 8.9f, 7.91f, 5.7f, 8.7f, 3.1f, 2.1f); | |||||
| var test_Y = np.array(1.84f, 2.273f, 3.2f, 2.831f, 2.92f, 3.24f, 1.35f, 1.03f); | |||||
| Console.WriteLine("Testing... (Mean square loss Comparison)"); | |||||
| var testing_cost = sess.run(tf.reduce_sum(tf.pow(pred - Y, 2.0f)) / (2.0f * test_X.shape[0]), | |||||
| (X, test_X), (Y, test_Y)); | |||||
| Console.WriteLine($"Testing cost={testing_cost}"); | |||||
| var diff = Math.Abs((float)training_cost - (float)testing_cost); | |||||
| Console.WriteLine($"Absolute mean square loss difference: {diff}"); | |||||
| return diff < 0.01; | |||||
| } | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| train_X = np.array(3.3f, 4.4f, 5.5f, 6.71f, 6.93f, 4.168f, 9.779f, 6.182f, 7.59f, 2.167f, | |||||
| 7.042f, 10.791f, 5.313f, 7.997f, 5.654f, 9.27f, 3.1f); | |||||
| train_Y = np.array(1.7f, 2.76f, 2.09f, 3.19f, 1.694f, 1.573f, 3.366f, 2.596f, 2.53f, 1.221f, | |||||
| 2.827f, 3.465f, 1.65f, 2.904f, 2.42f, 2.94f, 1.3f); | |||||
| n_samples = train_X.shape[0]; | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,190 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Diagnostics; | |||||
| using System.IO; | |||||
| using Tensorflow; | |||||
| using Tensorflow.Hub; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// A logistic regression learning algorithm example using TensorFlow library. | |||||
| /// This example is using the MNIST database of handwritten digits | |||||
| /// https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/2_BasicModels/logistic_regression.py | |||||
| /// </summary> | |||||
| public class LogisticRegression : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public string Name => "Logistic Regression"; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public int training_epochs = 10; | |||||
| public int? train_size = null; | |||||
| public int validation_size = 5000; | |||||
| public int? test_size = null; | |||||
| public int batch_size = 100; | |||||
| private float learning_rate = 0.01f; | |||||
| private int display_step = 1; | |||||
| Datasets<MnistDataSet> mnist; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| // tf Graph Input | |||||
| var x = tf.placeholder(tf.float32, new TensorShape(-1, 784)); // mnist data image of shape 28*28=784 | |||||
| var y = tf.placeholder(tf.float32, new TensorShape(-1, 10)); // 0-9 digits recognition => 10 classes | |||||
| // Set model weights | |||||
| var W = tf.Variable(tf.zeros(new Shape(784, 10))); | |||||
| var b = tf.Variable(tf.zeros(new Shape(10))); | |||||
| // Construct model | |||||
| var pred = tf.nn.softmax(tf.matmul(x, W) + b); // Softmax | |||||
| // Minimize error using cross entropy | |||||
| var cost = tf.reduce_mean(-tf.reduce_sum(y * tf.log(pred), reduction_indices: 1)); | |||||
| // Gradient Descent | |||||
| var optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost); | |||||
| // Initialize the variables (i.e. assign their default value) | |||||
| var init = tf.global_variables_initializer(); | |||||
| var sw = new Stopwatch(); | |||||
| using (var sess = tf.Session()) | |||||
| { | |||||
| // Run the initializer | |||||
| sess.run(init); | |||||
| // Training cycle | |||||
| foreach (var epoch in range(training_epochs)) | |||||
| { | |||||
| sw.Start(); | |||||
| var avg_cost = 0.0f; | |||||
| var total_batch = mnist.Train.NumOfExamples / batch_size; | |||||
| // Loop over all batches | |||||
| foreach (var i in range(total_batch)) | |||||
| { | |||||
| var (batch_xs, batch_ys) = mnist.Train.GetNextBatch(batch_size); | |||||
| // Run optimization op (backprop) and cost op (to get loss value) | |||||
| (_, float c) = sess.run((optimizer, cost), | |||||
| (x, batch_xs), | |||||
| (y, batch_ys)); | |||||
| // Compute average loss | |||||
| avg_cost += c / total_batch; | |||||
| } | |||||
| sw.Stop(); | |||||
| // Display logs per epoch step | |||||
| if ((epoch + 1) % display_step == 0) | |||||
| print($"Epoch: {(epoch + 1):D4} Cost: {avg_cost:G9} Elapse: {sw.ElapsedMilliseconds}ms"); | |||||
| sw.Reset(); | |||||
| } | |||||
| print("Optimization Finished!"); | |||||
| // SaveModel(sess); | |||||
| // Test model | |||||
| var correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1)); | |||||
| // Calculate accuracy | |||||
| var accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)); | |||||
| float acc = accuracy.eval(sess, (x, mnist.Test.Data), (y, mnist.Test.Labels)); | |||||
| print($"Accuracy: {acc:F4}"); | |||||
| return acc > 0.9; | |||||
| } | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| mnist = MnistModelLoader.LoadAsync(".resources/mnist", oneHot: true, trainSize: train_size, validationSize: validation_size, testSize: test_size, showProgressInConsole: true).Result; | |||||
| } | |||||
| public void SaveModel(Session sess) | |||||
| { | |||||
| var saver = tf.train.Saver(); | |||||
| var save_path = saver.save(sess, ".resources/logistic_regression/model.ckpt"); | |||||
| tf.train.write_graph(sess.graph, ".resources/logistic_regression", "model.pbtxt", as_text: true); | |||||
| FreezeGraph.freeze_graph(input_graph: ".resources/logistic_regression/model.pbtxt", | |||||
| input_saver: "", | |||||
| input_binary: false, | |||||
| input_checkpoint: ".resources/logistic_regression/model.ckpt", | |||||
| output_node_names: "Softmax", | |||||
| restore_op_name: "save/restore_all", | |||||
| filename_tensor_name: "save/Const:0", | |||||
| output_graph: ".resources/logistic_regression/model.pb", | |||||
| clear_devices: true, | |||||
| initializer_nodes: ""); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| var graph = new Graph().as_default(); | |||||
| graph.Import(Path.Join(".resources/logistic_regression", "model.pb")); | |||||
| // restoring the model | |||||
| // var saver = tf.train.import_meta_graph("logistic_regression/tensorflowModel.ckpt.meta"); | |||||
| // saver.restore(sess, tf.train.latest_checkpoint('logistic_regression')); | |||||
| var pred = graph.OperationByName("Softmax"); | |||||
| var output = pred.outputs[0]; | |||||
| var x = graph.OperationByName("Placeholder"); | |||||
| var input = x.outputs[0]; | |||||
| // predict | |||||
| var (batch_xs, batch_ys) = mnist.Train.GetNextBatch(10); | |||||
| var results = sess.run(output, new FeedItem(input, batch_xs[np.arange(1)])); | |||||
| if (results[0].argmax() == (batch_ys[0] as NDArray).argmax()) | |||||
| print("predicted OK!"); | |||||
| else | |||||
| throw new ValueError("predict error, should be 90% accuracy"); | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,221 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using Tensorflow; | |||||
| using NumSharp; | |||||
| using static Tensorflow.Binding; | |||||
| using System.IO; | |||||
| using TensorFlowNET.Examples.Utility; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// https://github.com/nicolov/naive_bayes_tensorflow | |||||
| /// </summary> | |||||
| public class NaiveBayesClassifier : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public string Name => "Naive Bayes Classifier"; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public NDArray X, y; | |||||
| public Normal dist { get; set; } | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| fit(X, y); | |||||
| // Create a regular grid and classify each point | |||||
| float x_min = X.amin(0).Data<float>()[0] - 0.5f; | |||||
| float y_min = X.amin(0).Data<float>()[1] - 0.5f; | |||||
| float x_max = X.amax(0).Data<float>()[1] + 0.5f; | |||||
| float y_max = X.amax(0).Data<float>()[1] + 0.5f; | |||||
| var (xx, yy) = np.meshgrid(np.linspace(x_min, x_max, 30), np.linspace(y_min, y_max, 30)); | |||||
| using (var sess = tf.Session()) | |||||
| { | |||||
| //var samples = np.vstack<float>(xx.ravel(), yy.ravel()); | |||||
| //samples = np.transpose(samples); | |||||
| var array = np.Load<double[,]>(Path.Join("nb", "nb_example.npy")); | |||||
| var samples = np.array(array).astype(np.float32); | |||||
| var Z = sess.run(predict(samples)); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| public void fit(NDArray X, NDArray y) | |||||
| { | |||||
| var unique_y = np.unique(y); | |||||
| var dic = new Dictionary<int, List<List<float>>>(); | |||||
| // Init uy in dic | |||||
| foreach (int uy in unique_y.Data<int>()) | |||||
| { | |||||
| dic.Add(uy, new List<List<float>>()); | |||||
| } | |||||
| // Separate training points by class | |||||
| // Shape : nb_classes * nb_samples * nb_features | |||||
| int maxCount = 0; | |||||
| for (int i = 0; i < y.size; i++) | |||||
| { | |||||
| var curClass = y[i]; | |||||
| var l = dic[curClass]; | |||||
| var pair = new List<float>(); | |||||
| pair.Add(X[i,0]); | |||||
| pair.Add(X[i, 1]); | |||||
| l.Add(pair); | |||||
| if (l.Count > maxCount) | |||||
| { | |||||
| maxCount = l.Count; | |||||
| } | |||||
| dic[curClass] = l; | |||||
| } | |||||
| float[,,] points = new float[dic.Count, maxCount, X.shape[1]]; | |||||
| foreach (KeyValuePair<int, List<List<float>>> kv in dic) | |||||
| { | |||||
| int j = (int) kv.Key; | |||||
| for (int i = 0; i < maxCount; i++) | |||||
| { | |||||
| for (int k = 0; k < X.shape[1]; k++) | |||||
| { | |||||
| points[j, i, k] = kv.Value[i][k]; | |||||
| } | |||||
| } | |||||
| } | |||||
| var points_by_class = np.array(points); | |||||
| // estimate mean and variance for each class / feature | |||||
| // shape : nb_classes * nb_features | |||||
| var cons = tf.constant(points_by_class); | |||||
| var tup = tf.nn.moments(cons, new int[]{1}); | |||||
| var mean = tup.Item1; | |||||
| var variance = tup.Item2; | |||||
| // Create a 3x2 univariate normal distribution with the | |||||
| // Known mean and variance | |||||
| var dist = tf.distributions.Normal(mean, tf.sqrt(variance)); | |||||
| this.dist = dist; | |||||
| } | |||||
| public Tensor predict(NDArray X) | |||||
| { | |||||
| if (dist == null) | |||||
| { | |||||
| throw new ArgumentNullException("cant not find the model (normal distribution)!"); | |||||
| } | |||||
| int nb_classes = (int) dist.scale().shape[0]; | |||||
| int nb_features = (int)dist.scale().shape[1]; | |||||
| // Conditional probabilities log P(x|c) with shape | |||||
| // (nb_samples, nb_classes) | |||||
| var t1= ops.convert_to_tensor(X, TF_DataType.TF_FLOAT); | |||||
| var t2 = ops.convert_to_tensor(new int[] { 1, nb_classes }); | |||||
| Tensor tile = tf.tile(t1, t2); | |||||
| var t3 = ops.convert_to_tensor(new int[] { -1, nb_classes, nb_features }); | |||||
| Tensor r = tf.reshape(tile, t3); | |||||
| var cond_probs = tf.reduce_sum(dist.log_prob(r), 2); | |||||
| // uniform priors | |||||
| float[] tem = new float[nb_classes]; | |||||
| for (int i = 0; i < tem.Length; i++) | |||||
| { | |||||
| tem[i] = 1.0f / nb_classes; | |||||
| } | |||||
| var priors = np.log(np.array<float>(tem)); | |||||
| // posterior log probability, log P(c) + log P(x|c) | |||||
| var joint_likelihood = tf.add(ops.convert_to_tensor(priors, TF_DataType.TF_FLOAT), cond_probs); | |||||
| // normalize to get (log)-probabilities | |||||
| var norm_factor = tf.reduce_logsumexp(joint_likelihood, new int[] { 1 }, keepdims: true); | |||||
| var log_prob = joint_likelihood - norm_factor; | |||||
| // exp to get the actual probabilities | |||||
| return tf.exp(log_prob); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| #region Training data | |||||
| X = np.array(new float[,] { | |||||
| {5.1f, 3.5f}, {4.9f, 3.0f}, {4.7f, 3.2f}, {4.6f, 3.1f}, {5.0f, 3.6f}, {5.4f, 3.9f}, | |||||
| {4.6f, 3.4f}, {5.0f, 3.4f}, {4.4f, 2.9f}, {4.9f, 3.1f}, {5.4f, 3.7f}, {4.8f, 3.4f}, | |||||
| {4.8f, 3.0f}, {4.3f, 3.0f}, {5.8f, 4.0f}, {5.7f, 4.4f}, {5.4f, 3.9f}, {5.1f, 3.5f}, | |||||
| {5.7f, 3.8f}, {5.1f, 3.8f}, {5.4f, 3.4f}, {5.1f, 3.7f}, {5.1f, 3.3f}, {4.8f, 3.4f}, | |||||
| {5.0f, 3.0f}, {5.0f, 3.4f}, {5.2f, 3.5f}, {5.2f, 3.4f}, {4.7f, 3.2f}, {4.8f, 3.1f}, | |||||
| {5.4f, 3.4f}, {5.2f, 4.1f}, {5.5f, 4.2f}, {4.9f, 3.1f}, {5.0f, 3.2f}, {5.5f, 3.5f}, | |||||
| {4.9f, 3.6f}, {4.4f, 3.0f}, {5.1f, 3.4f}, {5.0f, 3.5f}, {4.5f, 2.3f}, {4.4f, 3.2f}, | |||||
| {5.0f, 3.5f}, {5.1f, 3.8f}, {4.8f, 3.0f}, {5.1f, 3.8f}, {4.6f, 3.2f}, {5.3f, 3.7f}, | |||||
| {5.0f, 3.3f}, {7.0f, 3.2f}, {6.4f, 3.2f}, {6.9f, 3.1f}, {5.5f, 2.3f}, {6.5f, 2.8f}, | |||||
| {5.7f, 2.8f}, {6.3f, 3.3f}, {4.9f, 2.4f}, {6.6f, 2.9f}, {5.2f, 2.7f}, {5.0f, 2.0f}, | |||||
| {5.9f, 3.0f}, {6.0f, 2.2f}, {6.1f, 2.9f}, {5.6f, 2.9f}, {6.7f, 3.1f}, {5.6f, 3.0f}, | |||||
| {5.8f, 2.7f}, {6.2f, 2.2f}, {5.6f, 2.5f}, {5.9f, 3.0f}, {6.1f, 2.8f}, {6.3f, 2.5f}, | |||||
| {6.1f, 2.8f}, {6.4f, 2.9f}, {6.6f, 3.0f}, {6.8f, 2.8f}, {6.7f, 3.0f}, {6.0f, 2.9f}, | |||||
| {5.7f, 2.6f}, {5.5f, 2.4f}, {5.5f, 2.4f}, {5.8f, 2.7f}, {6.0f, 2.7f}, {5.4f, 3.0f}, | |||||
| {6.0f, 3.4f}, {6.7f, 3.1f}, {6.3f, 2.3f}, {5.6f, 3.0f}, {5.5f, 2.5f}, {5.5f, 2.6f}, | |||||
| {6.1f, 3.0f}, {5.8f, 2.6f}, {5.0f, 2.3f}, {5.6f, 2.7f}, {5.7f, 3.0f}, {5.7f, 2.9f}, | |||||
| {6.2f, 2.9f}, {5.1f, 2.5f}, {5.7f, 2.8f}, {6.3f, 3.3f}, {5.8f, 2.7f}, {7.1f, 3.0f}, | |||||
| {6.3f, 2.9f}, {6.5f, 3.0f}, {7.6f, 3.0f}, {4.9f, 2.5f}, {7.3f, 2.9f}, {6.7f, 2.5f}, | |||||
| {7.2f, 3.6f}, {6.5f, 3.2f}, {6.4f, 2.7f}, {6.8f, 3.0f}, {5.7f, 2.5f}, {5.8f, 2.8f}, | |||||
| {6.4f, 3.2f}, {6.5f, 3.0f}, {7.7f, 3.8f}, {7.7f, 2.6f}, {6.0f, 2.2f}, {6.9f, 3.2f}, | |||||
| {5.6f, 2.8f}, {7.7f, 2.8f}, {6.3f, 2.7f}, {6.7f, 3.3f}, {7.2f, 3.2f}, {6.2f, 2.8f}, | |||||
| {6.1f, 3.0f}, {6.4f, 2.8f}, {7.2f, 3.0f}, {7.4f, 2.8f}, {7.9f, 3.8f}, {6.4f, 2.8f}, | |||||
| {6.3f, 2.8f}, {6.1f, 2.6f}, {7.7f, 3.0f}, {6.3f, 3.4f}, {6.4f, 3.1f}, {6.0f, 3.0f}, | |||||
| {6.9f, 3.1f}, {6.7f, 3.1f}, {6.9f, 3.1f}, {5.8f, 2.7f}, {6.8f, 3.2f}, {6.7f, 3.3f}, | |||||
| {6.7f, 3.0f}, {6.3f, 2.5f}, {6.5f, 3.0f}, {6.2f, 3.4f}, {5.9f, 3.0f}, {5.8f, 3.0f}}); | |||||
| y = np.array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||||
| 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |||||
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |||||
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |||||
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |||||
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); | |||||
| string url = "https://raw.githubusercontent.com/SciSharp/TensorFlow.NET/master/data/nb_example.npy"; | |||||
| Web.Download(url, "nb", "nb_example.npy"); | |||||
| #endregion | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,118 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using Tensorflow; | |||||
| using Tensorflow.Hub; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// A nearest neighbor learning algorithm example | |||||
| /// This example is using the MNIST database of handwritten digits | |||||
| /// https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/2_BasicModels/nearest_neighbor.py | |||||
| /// </summary> | |||||
| public class NearestNeighbor : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public string Name => "Nearest Neighbor"; | |||||
| Datasets<MnistDataSet> mnist; | |||||
| NDArray Xtr, Ytr, Xte, Yte; | |||||
| public int? TrainSize = null; | |||||
| public int ValidationSize = 5000; | |||||
| public int? TestSize = null; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public bool Run() | |||||
| { | |||||
| // tf Graph Input | |||||
| var xtr = tf.placeholder(tf.float32, new TensorShape(-1, 784)); | |||||
| var xte = tf.placeholder(tf.float32, new TensorShape(784)); | |||||
| // Nearest Neighbor calculation using L1 Distance | |||||
| // Calculate L1 Distance | |||||
| var distance = tf.reduce_sum(tf.abs(tf.add(xtr, tf.negative(xte))), reduction_indices: 1); | |||||
| // Prediction: Get min distance index (Nearest neighbor) | |||||
| var pred = tf.arg_min(distance, 0); | |||||
| float accuracy = 0f; | |||||
| // Initialize the variables (i.e. assign their default value) | |||||
| var init = tf.global_variables_initializer(); | |||||
| using (var sess = tf.Session()) | |||||
| { | |||||
| // Run the initializer | |||||
| sess.run(init); | |||||
| PrepareData(); | |||||
| foreach(int i in range(Xte.shape[0])) | |||||
| { | |||||
| // Get nearest neighbor | |||||
| long nn_index = sess.run(pred, (xtr, Xtr), (xte, Xte[i])); | |||||
| // Get nearest neighbor class label and compare it to its true label | |||||
| int index = (int)nn_index; | |||||
| if (i % 10 == 0 || i == 0) | |||||
| print($"Test {i} Prediction: {np.argmax(Ytr[index])} True Class: {np.argmax(Yte[i])}"); | |||||
| // Calculate accuracy | |||||
| if (np.argmax(Ytr[index]) == np.argmax(Yte[i])) | |||||
| accuracy += 1f/ Xte.shape[0]; | |||||
| } | |||||
| print($"Accuracy: {accuracy}"); | |||||
| } | |||||
| return accuracy > 0.8; | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| mnist = MnistModelLoader.LoadAsync(".resources/mnist", oneHot: true, trainSize: TrainSize, validationSize: ValidationSize, testSize: TestSize, showProgressInConsole: true).Result; | |||||
| // In this example, we limit mnist data | |||||
| (Xtr, Ytr) = mnist.Train.GetNextBatch(TrainSize == null ? 5000 : TrainSize.Value / 100); // 5000 for training (nn candidates) | |||||
| (Xte, Yte) = mnist.Test.GetNextBatch(TestSize == null ? 200 : TestSize.Value / 100); // 200 for testing | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,187 +0,0 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Basic Operations example using TensorFlow library. | |||||
| /// https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/1_Introduction/basic_operations.py | |||||
| /// </summary> | |||||
| public class BasicOperations : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public string Name => "Basic Operations"; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| private Session sess; | |||||
| public bool Run() | |||||
| { | |||||
| // Basic constant operations | |||||
| // The value returned by the constructor represents the output | |||||
| // of the Constant op. | |||||
| var a = tf.constant(2); | |||||
| var b = tf.constant(3); | |||||
| // Launch the default graph. | |||||
| using (sess = tf.Session()) | |||||
| { | |||||
| Console.WriteLine("a=2, b=3"); | |||||
| Console.WriteLine($"Addition with constants: {sess.run(a + b)}"); | |||||
| Console.WriteLine($"Multiplication with constants: {sess.run(a * b)}"); | |||||
| } | |||||
| // Basic Operations with variable as graph input | |||||
| // The value returned by the constructor represents the output | |||||
| // of the Variable op. (define as input when running session) | |||||
| // tf Graph input | |||||
| a = tf.placeholder(tf.int16); | |||||
| b = tf.placeholder(tf.int16); | |||||
| // Define some operations | |||||
| var add = tf.add(a, b); | |||||
| var mul = tf.multiply(a, b); | |||||
| // Launch the default graph. | |||||
| using(sess = tf.Session()) | |||||
| { | |||||
| var feed_dict = new FeedItem[] | |||||
| { | |||||
| new FeedItem(a, (short)2), | |||||
| new FeedItem(b, (short)3) | |||||
| }; | |||||
| // Run every operation with variable input | |||||
| Console.WriteLine($"Addition with variables: {sess.run(add, feed_dict)}"); | |||||
| Console.WriteLine($"Multiplication with variables: {sess.run(mul, feed_dict)}"); | |||||
| } | |||||
| // ---------------- | |||||
| // More in details: | |||||
| // Matrix Multiplication from TensorFlow official tutorial | |||||
| // Create a Constant op that produces a 1x2 matrix. The op is | |||||
| // added as a node to the default graph. | |||||
| // | |||||
| // The value returned by the constructor represents the output | |||||
| // of the Constant op. | |||||
| var nd1 = np.array(3, 3).reshape(1, 2); | |||||
| var matrix1 = tf.constant(nd1); | |||||
| // Create another Constant that produces a 2x1 matrix. | |||||
| var nd2 = np.array(2, 2).reshape(2, 1); | |||||
| var matrix2 = tf.constant(nd2); | |||||
| // Create a Matmul op that takes 'matrix1' and 'matrix2' as inputs. | |||||
| // The returned value, 'product', represents the result of the matrix | |||||
| // multiplication. | |||||
| var product = tf.matmul(matrix1, matrix2); | |||||
| // To run the matmul op we call the session 'run()' method, passing 'product' | |||||
| // which represents the output of the matmul op. This indicates to the call | |||||
| // that we want to get the output of the matmul op back. | |||||
| // | |||||
| // All inputs needed by the op are run automatically by the session. They | |||||
| // typically are run in parallel. | |||||
| // | |||||
| // The call 'run(product)' thus causes the execution of threes ops in the | |||||
| // graph: the two constants and matmul. | |||||
| // | |||||
| // The output of the op is returned in 'result' as a numpy `ndarray` object. | |||||
| using (sess = tf.Session()) | |||||
| { | |||||
| var result = sess.run(product); | |||||
| Console.WriteLine(result.ToString()); // ==> [[ 12.]] | |||||
| }; | |||||
| // `BatchMatMul` is actually embedded into the `MatMul` operation on the tf.dll side. Every time we ask | |||||
| // for a multiplication between matrices with rank > 2, the first rank - 2 dimensions are checked to be consistent | |||||
| // across the two matrices and a common matrix multiplication is done on the residual 2 dimensions. | |||||
| // | |||||
| // np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9]).reshape(3, 3, 3) | |||||
| // array([[[1, 2, 3], | |||||
| // [4, 5, 6], | |||||
| // [7, 8, 9]], | |||||
| // | |||||
| // [[1, 2, 3], | |||||
| // [4, 5, 6], | |||||
| // [7, 8, 9]], | |||||
| // | |||||
| // [[1, 2, 3], | |||||
| // [4, 5, 6], | |||||
| // [7, 8, 9]]]) | |||||
| var firstTensor = tf.convert_to_tensor( | |||||
| np.reshape( | |||||
| np.array<float>(1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9), | |||||
| 3, 3, 3)); | |||||
| // | |||||
| // np.array([0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0]).reshape(3,3,2) | |||||
| // array([[[0, 1], | |||||
| // [0, 1], | |||||
| // [0, 1]], | |||||
| // | |||||
| // [[0, 1], | |||||
| // [0, 0], | |||||
| // [1, 0]], | |||||
| // | |||||
| // [[1, 0], | |||||
| // [1, 0], | |||||
| // [1, 0]]]) | |||||
| var secondTensor = tf.convert_to_tensor( | |||||
| np.reshape( | |||||
| np.array<float>(0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0), | |||||
| 3, 3, 2)); | |||||
| var batchMul = tf.batch_matmul(firstTensor, secondTensor); | |||||
| var checkTensor = np.array<float>(0, 6, 0, 15, 0, 24, 3, 1, 6, 4, 9, 7, 6, 0, 15, 0, 24, 0); | |||||
| using (var sess = tf.Session()) | |||||
| { | |||||
| var result = sess.run(batchMul); | |||||
| Console.WriteLine(result.ToString()); | |||||
| // | |||||
| // ==> array([[[0, 6], | |||||
| // [0, 15], | |||||
| // [0, 24]], | |||||
| // | |||||
| // [[ 3, 1], | |||||
| // [ 6, 4], | |||||
| // [ 9, 7]], | |||||
| // | |||||
| // [[ 6, 0], | |||||
| // [15, 0], | |||||
| // [24, 0]]]) | |||||
| return np.reshape(result, 18) | |||||
| .array_equal(checkTensor); | |||||
| } | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,66 +0,0 @@ | |||||
| using System; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Simple hello world using TensorFlow | |||||
| /// https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/1_Introduction/helloworld.py | |||||
| /// </summary> | |||||
| public class HelloWorld : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public string Name => "Hello World"; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public bool Run() | |||||
| { | |||||
| /* Create a Constant op | |||||
| The op is added as a node to the default graph. | |||||
| The value returned by the constructor represents the output | |||||
| of the Constant op. */ | |||||
| var str = "Hello, TensorFlow.NET!"; | |||||
| var hello = tf.constant(str); | |||||
| // Start tf session | |||||
| using (var sess = tf.Session()) | |||||
| { | |||||
| // Run the op | |||||
| var result = sess.run(hello); | |||||
| Console.WriteLine(result.ToString()); | |||||
| return result.ToString().Equals(str); | |||||
| } | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,59 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using Tensorflow; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Interface of Example project | |||||
| /// All example should implement IExample so the entry program will find it. | |||||
| /// </summary> | |||||
| public interface IExample | |||||
| { | |||||
| /// <summary> | |||||
| /// True to run example | |||||
| /// </summary> | |||||
| bool Enabled { get; set; } | |||||
| /// <summary> | |||||
| /// Set true to import the computation graph instead of building it. | |||||
| /// </summary> | |||||
| bool IsImportingGraph { get; set; } | |||||
| string Name { get; } | |||||
| bool Run(); | |||||
| /// <summary> | |||||
| /// Build dataflow graph, train and predict | |||||
| /// </summary> | |||||
| /// <returns></returns> | |||||
| void Train(Session sess); | |||||
| void Test(Session sess); | |||||
| void Predict(Session sess); | |||||
| Graph ImportGraph(); | |||||
| Graph BuildGraph(); | |||||
| /// <summary> | |||||
| /// Prepare dataset | |||||
| /// </summary> | |||||
| void PrepareData(); | |||||
| } | |||||
| } | |||||
| @@ -1,73 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| using Tensorflow; | |||||
| using TensorFlowDatasets; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// https://www.tensorflow.org/tutorials/images/deep_cnn | |||||
| /// </summary> | |||||
| public class CIFAR10_CNN : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public string Name => "CIFAR-10 CNN"; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| return true; | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| var tfds = new DatasetBuilder(); | |||||
| tfds.download_and_prepare(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,338 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Diagnostics; | |||||
| using Tensorflow; | |||||
| using Tensorflow.Hub; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Convolutional Neural Network classifier for Hand Written Digits | |||||
| /// CNN architecture with two convolutional layers, followed by two fully-connected layers at the end. | |||||
| /// Use Stochastic Gradient Descent (SGD) optimizer. | |||||
| /// http://www.easy-tf.com/tf-tutorials/convolutional-neural-nets-cnns/cnn1 | |||||
| /// </summary> | |||||
| public class DigitRecognitionCNN : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public string Name => "MNIST CNN"; | |||||
| string logs_path = "logs"; | |||||
| const int img_h = 28, img_w = 28; // MNIST images are 28x28 | |||||
| int n_classes = 10; // Number of classes, one class per digit | |||||
| int n_channels = 1; | |||||
| // Hyper-parameters | |||||
| int epochs = 5; // accuracy > 98% | |||||
| int batch_size = 100; | |||||
| float learning_rate = 0.001f; | |||||
| Datasets<MnistDataSet> mnist; | |||||
| // Network configuration | |||||
| // 1st Convolutional Layer | |||||
| int filter_size1 = 5; // Convolution filters are 5 x 5 pixels. | |||||
| int num_filters1 = 16; // There are 16 of these filters. | |||||
| int stride1 = 1; // The stride of the sliding window | |||||
| // 2nd Convolutional Layer | |||||
| int filter_size2 = 5; // Convolution filters are 5 x 5 pixels. | |||||
| int num_filters2 = 32;// There are 32 of these filters. | |||||
| int stride2 = 1; // The stride of the sliding window | |||||
| // Fully-connected layer. | |||||
| int h1 = 128; // Number of neurons in fully-connected layer. | |||||
| Tensor x, y; | |||||
| Tensor loss, accuracy, cls_prediction; | |||||
| Operation optimizer; | |||||
| int display_freq = 100; | |||||
| float accuracy_test = 0f; | |||||
| float loss_test = 1f; | |||||
| NDArray x_train, y_train; | |||||
| NDArray x_valid, y_valid; | |||||
| NDArray x_test, y_test; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| BuildGraph(); | |||||
| using (var sess = tf.Session()) | |||||
| { | |||||
| Train(sess); | |||||
| Test(sess); | |||||
| } | |||||
| return loss_test < 0.05 && accuracy_test > 0.98; | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| var graph = new Graph().as_default(); | |||||
| tf_with(tf.name_scope("Input"), delegate | |||||
| { | |||||
| // Placeholders for inputs (x) and outputs(y) | |||||
| x = tf.placeholder(tf.float32, shape: (-1, img_h, img_w, n_channels), name: "X"); | |||||
| y = tf.placeholder(tf.float32, shape: (-1, n_classes), name: "Y"); | |||||
| }); | |||||
| var conv1 = conv_layer(x, filter_size1, num_filters1, stride1, name: "conv1"); | |||||
| var pool1 = max_pool(conv1, ksize: 2, stride: 2, name: "pool1"); | |||||
| var conv2 = conv_layer(pool1, filter_size2, num_filters2, stride2, name: "conv2"); | |||||
| var pool2 = max_pool(conv2, ksize: 2, stride: 2, name: "pool2"); | |||||
| var layer_flat = flatten_layer(pool2); | |||||
| var fc1 = fc_layer(layer_flat, h1, "FC1", use_relu: true); | |||||
| var output_logits = fc_layer(fc1, n_classes, "OUT", use_relu: false); | |||||
| tf_with(tf.variable_scope("Train"), delegate | |||||
| { | |||||
| tf_with(tf.variable_scope("Loss"), delegate | |||||
| { | |||||
| loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels: y, logits: output_logits), name: "loss"); | |||||
| }); | |||||
| tf_with(tf.variable_scope("Optimizer"), delegate | |||||
| { | |||||
| optimizer = tf.train.AdamOptimizer(learning_rate: learning_rate, name: "Adam-op").minimize(loss); | |||||
| }); | |||||
| tf_with(tf.variable_scope("Accuracy"), delegate | |||||
| { | |||||
| var correct_prediction = tf.equal(tf.argmax(output_logits, 1), tf.argmax(y, 1), name: "correct_pred"); | |||||
| accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name: "accuracy"); | |||||
| }); | |||||
| tf_with(tf.variable_scope("Prediction"), delegate | |||||
| { | |||||
| cls_prediction = tf.argmax(output_logits, axis: 1, name: "predictions"); | |||||
| }); | |||||
| }); | |||||
| return graph; | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| // Number of training iterations in each epoch | |||||
| var num_tr_iter = y_train.shape[0] / batch_size; | |||||
| var init = tf.global_variables_initializer(); | |||||
| sess.run(init); | |||||
| float loss_val = 100.0f; | |||||
| float accuracy_val = 0f; | |||||
| var sw = new Stopwatch(); | |||||
| sw.Start(); | |||||
| foreach (var epoch in range(epochs)) | |||||
| { | |||||
| print($"Training epoch: {epoch + 1}"); | |||||
| // Randomly shuffle the training data at the beginning of each epoch | |||||
| (x_train, y_train) = mnist.Randomize(x_train, y_train); | |||||
| foreach (var iteration in range(num_tr_iter)) | |||||
| { | |||||
| var start = iteration * batch_size; | |||||
| var end = (iteration + 1) * batch_size; | |||||
| var (x_batch, y_batch) = mnist.GetNextBatch(x_train, y_train, start, end); | |||||
| // Run optimization op (backprop) | |||||
| sess.run(optimizer, (x, x_batch), (y, y_batch)); | |||||
| if (iteration % display_freq == 0) | |||||
| { | |||||
| // Calculate and display the batch loss and accuracy | |||||
| var result = sess.run(new[] { loss, accuracy }, new FeedItem(x, x_batch), new FeedItem(y, y_batch)); | |||||
| loss_val = result[0]; | |||||
| accuracy_val = result[1]; | |||||
| print($"iter {iteration.ToString("000")}: Loss={loss_val.ToString("0.0000")}, Training Accuracy={accuracy_val.ToString("P")} {sw.ElapsedMilliseconds}ms"); | |||||
| sw.Restart(); | |||||
| } | |||||
| } | |||||
| // Run validation after every epoch | |||||
| (loss_val, accuracy_val) = sess.run((loss, accuracy), (x, x_valid), (y, y_valid)); | |||||
| print("---------------------------------------------------------"); | |||||
| print($"Epoch: {epoch + 1}, validation loss: {loss_val.ToString("0.0000")}, validation accuracy: {accuracy_val.ToString("P")}"); | |||||
| print("---------------------------------------------------------"); | |||||
| } | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| (loss_test, accuracy_test) = sess.run((loss, accuracy), (x, x_test), (y, y_test)); | |||||
| print("---------------------------------------------------------"); | |||||
| print($"Test loss: {loss_test.ToString("0.0000")}, test accuracy: {accuracy_test.ToString("P")}"); | |||||
| print("---------------------------------------------------------"); | |||||
| } | |||||
| /// <summary> | |||||
| /// Create a 2D convolution layer | |||||
| /// </summary> | |||||
| /// <param name="x">input from previous layer</param> | |||||
| /// <param name="filter_size">size of each filter</param> | |||||
| /// <param name="num_filters">number of filters(or output feature maps)</param> | |||||
| /// <param name="stride">filter stride</param> | |||||
| /// <param name="name">layer name</param> | |||||
| /// <returns>The output array</returns> | |||||
| private Tensor conv_layer(Tensor x, int filter_size, int num_filters, int stride, string name) | |||||
| { | |||||
| return tf_with(tf.variable_scope(name), delegate { | |||||
| var num_in_channel = x.shape[x.NDims - 1]; | |||||
| var shape = new[] { filter_size, filter_size, num_in_channel, num_filters }; | |||||
| var W = weight_variable("W", shape); | |||||
| // var tf.summary.histogram("weight", W); | |||||
| var b = bias_variable("b", new[] { num_filters }); | |||||
| // tf.summary.histogram("bias", b); | |||||
| var layer = tf.nn.conv2d(x, W, | |||||
| strides: new[] { 1, stride, stride, 1 }, | |||||
| padding: "SAME"); | |||||
| layer += b; | |||||
| return tf.nn.relu(layer); | |||||
| }); | |||||
| } | |||||
| /// <summary> | |||||
| /// Create a max pooling layer | |||||
| /// </summary> | |||||
| /// <param name="x">input to max-pooling layer</param> | |||||
| /// <param name="ksize">size of the max-pooling filter</param> | |||||
| /// <param name="stride">stride of the max-pooling filter</param> | |||||
| /// <param name="name">layer name</param> | |||||
| /// <returns>The output array</returns> | |||||
| private Tensor max_pool(Tensor x, int ksize, int stride, string name) | |||||
| { | |||||
| return tf.nn.max_pool(x, | |||||
| ksize: new[] { 1, ksize, ksize, 1 }, | |||||
| strides: new[] { 1, stride, stride, 1 }, | |||||
| padding: "SAME", | |||||
| name: name); | |||||
| } | |||||
| /// <summary> | |||||
| /// Flattens the output of the convolutional layer to be fed into fully-connected layer | |||||
| /// </summary> | |||||
| /// <param name="layer">input array</param> | |||||
| /// <returns>flattened array</returns> | |||||
| private Tensor flatten_layer(Tensor layer) | |||||
| { | |||||
| return tf_with(tf.variable_scope("Flatten_layer"), delegate | |||||
| { | |||||
| var layer_shape = layer.TensorShape; | |||||
| var num_features = layer_shape[new Slice(1, 4)].size; | |||||
| var layer_flat = tf.reshape(layer, new[] { -1, num_features }); | |||||
| return layer_flat; | |||||
| }); | |||||
| } | |||||
| /// <summary> | |||||
| /// Create a weight variable with appropriate initialization | |||||
| /// </summary> | |||||
| /// <param name="name"></param> | |||||
| /// <param name="shape"></param> | |||||
| /// <returns></returns> | |||||
| private RefVariable weight_variable(string name, int[] shape) | |||||
| { | |||||
| var initer = tf.truncated_normal_initializer(stddev: 0.01f); | |||||
| return tf.get_variable(name, | |||||
| dtype: tf.float32, | |||||
| shape: shape, | |||||
| initializer: initer); | |||||
| } | |||||
| /// <summary> | |||||
| /// Create a bias variable with appropriate initialization | |||||
| /// </summary> | |||||
| /// <param name="name"></param> | |||||
| /// <param name="shape"></param> | |||||
| /// <returns></returns> | |||||
| private RefVariable bias_variable(string name, int[] shape) | |||||
| { | |||||
| var initial = tf.constant(0f, shape: shape, dtype: tf.float32); | |||||
| return tf.get_variable(name, | |||||
| dtype: tf.float32, | |||||
| initializer: initial); | |||||
| } | |||||
| /// <summary> | |||||
| /// Create a fully-connected layer | |||||
| /// </summary> | |||||
| /// <param name="x">input from previous layer</param> | |||||
| /// <param name="num_units">number of hidden units in the fully-connected layer</param> | |||||
| /// <param name="name">layer name</param> | |||||
| /// <param name="use_relu">boolean to add ReLU non-linearity (or not)</param> | |||||
| /// <returns>The output array</returns> | |||||
| private Tensor fc_layer(Tensor x, int num_units, string name, bool use_relu = true) | |||||
| { | |||||
| return tf_with(tf.variable_scope(name), delegate | |||||
| { | |||||
| var in_dim = x.shape[1]; | |||||
| var W = weight_variable("W_" + name, shape: new[] { in_dim, num_units }); | |||||
| var b = bias_variable("b_" + name, new[] { num_units }); | |||||
| var layer = tf.matmul(x, W) + b; | |||||
| if (use_relu) | |||||
| layer = tf.nn.relu(layer); | |||||
| return layer; | |||||
| }); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| mnist = MnistModelLoader.LoadAsync(".resources/mnist", oneHot: true, showProgressInConsole: true).Result; | |||||
| (x_train, y_train) = Reformat(mnist.Train.Data, mnist.Train.Labels); | |||||
| (x_valid, y_valid) = Reformat(mnist.Validation.Data, mnist.Validation.Labels); | |||||
| (x_test, y_test) = Reformat(mnist.Test.Data, mnist.Test.Labels); | |||||
| print("Size of:"); | |||||
| print($"- Training-set:\t\t{len(mnist.Train.Data)}"); | |||||
| print($"- Validation-set:\t{len(mnist.Validation.Data)}"); | |||||
| } | |||||
| /// <summary> | |||||
| /// Reformats the data to the format acceptable for convolutional layers | |||||
| /// </summary> | |||||
| /// <param name="x"></param> | |||||
| /// <param name="y"></param> | |||||
| /// <returns></returns> | |||||
| private (NDArray, NDArray) Reformat(NDArray x, NDArray y) | |||||
| { | |||||
| var (img_size, num_ch, num_class) = (np.sqrt(x.shape[1]).astype(np.int32), 1, len(np.unique(np.argmax(y, 1)))); | |||||
| var dataset = x.reshape(x.shape[0], img_size, img_size, num_ch).astype(np.float32); | |||||
| //y[0] = np.arange(num_class) == y[0]; | |||||
| //var labels = (np.arange(num_class) == y.reshape(y.shape[0], 1, y.shape[1])).astype(np.float32); | |||||
| return (dataset, y); | |||||
| } | |||||
| public Graph ImportGraph() => throw new NotImplementedException(); | |||||
| public void Predict(Session sess) => throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| @@ -1,182 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Diagnostics; | |||||
| using Tensorflow; | |||||
| using Tensorflow.Hub; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Neural Network classifier for Hand Written Digits | |||||
| /// Sample Neural Network architecture with two layers implemented for classifying MNIST digits. | |||||
| /// Use Stochastic Gradient Descent (SGD) optimizer. | |||||
| /// http://www.easy-tf.com/tf-tutorials/neural-networks | |||||
| /// </summary> | |||||
| public class DigitRecognitionNN : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public string Name => "Digits Recognition Neural Network"; | |||||
| const int img_h = 28; | |||||
| const int img_w = 28; | |||||
| int img_size_flat = img_h * img_w; // 784, the total number of pixels | |||||
| int n_classes = 10; // Number of classes, one class per digit | |||||
| // Hyper-parameters | |||||
| int epochs = 10; | |||||
| int batch_size = 100; | |||||
| float learning_rate = 0.001f; | |||||
| int h1 = 200; // number of nodes in the 1st hidden layer | |||||
| Datasets<MnistDataSet> mnist; | |||||
| Tensor x, y; | |||||
| Tensor loss, accuracy; | |||||
| Operation optimizer; | |||||
| int display_freq = 100; | |||||
| float accuracy_test = 0f; | |||||
| float loss_test = 1f; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| BuildGraph(); | |||||
| using (var sess = tf.Session()) | |||||
| { | |||||
| Train(sess); | |||||
| Test(sess); | |||||
| }; | |||||
| return loss_test < 0.09 && accuracy_test > 0.95; | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| var graph = new Graph().as_default(); | |||||
| // Placeholders for inputs (x) and outputs(y) | |||||
| x = tf.placeholder(tf.float32, shape: (-1, img_size_flat), name: "X"); | |||||
| y = tf.placeholder(tf.float32, shape: (-1, n_classes), name: "Y"); | |||||
| // Create a fully-connected layer with h1 nodes as hidden layer | |||||
| var fc1 = fc_layer(x, h1, "FC1", use_relu: true); | |||||
| // Create a fully-connected layer with n_classes nodes as output layer | |||||
| var output_logits = fc_layer(fc1, n_classes, "OUT", use_relu: false); | |||||
| // Define the loss function, optimizer, and accuracy | |||||
| var logits = tf.nn.softmax_cross_entropy_with_logits(labels: y, logits: output_logits); | |||||
| loss = tf.reduce_mean(logits, name: "loss"); | |||||
| optimizer = tf.train.AdamOptimizer(learning_rate: learning_rate, name: "Adam-op").minimize(loss); | |||||
| var correct_prediction = tf.equal(tf.argmax(output_logits, 1), tf.argmax(y, 1), name: "correct_pred"); | |||||
| accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name: "accuracy"); | |||||
| // Network predictions | |||||
| var cls_prediction = tf.argmax(output_logits, axis: 1, name: "predictions"); | |||||
| return graph; | |||||
| } | |||||
| private Tensor fc_layer(Tensor x, int num_units, string name, bool use_relu = true) | |||||
| { | |||||
| var in_dim = x.shape[1]; | |||||
| var initer = tf.truncated_normal_initializer(stddev: 0.01f); | |||||
| var W = tf.get_variable("W_" + name, | |||||
| dtype: tf.float32, | |||||
| shape: (in_dim, num_units), | |||||
| initializer: initer); | |||||
| var initial = tf.constant(0f, num_units); | |||||
| var b = tf.get_variable("b_" + name, | |||||
| dtype: tf.float32, | |||||
| initializer: initial); | |||||
| var layer = tf.matmul(x, W) + b; | |||||
| if (use_relu) | |||||
| layer = tf.nn.relu(layer); | |||||
| return layer; | |||||
| } | |||||
| public Graph ImportGraph() => throw new NotImplementedException(); | |||||
| public void Predict(Session sess) => throw new NotImplementedException(); | |||||
| public void PrepareData() | |||||
| { | |||||
| mnist = MnistModelLoader.LoadAsync(".resources/mnist", oneHot: true, showProgressInConsole: true).Result; | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| // Number of training iterations in each epoch | |||||
| var num_tr_iter = mnist.Train.Labels.shape[0] / batch_size; | |||||
| var init = tf.global_variables_initializer(); | |||||
| sess.run(init); | |||||
| float loss_val = 100.0f; | |||||
| float accuracy_val = 0f; | |||||
| var sw = new Stopwatch(); | |||||
| sw.Start(); | |||||
| foreach (var epoch in range(epochs)) | |||||
| { | |||||
| print($"Training epoch: {epoch + 1}"); | |||||
| // Randomly shuffle the training data at the beginning of each epoch | |||||
| var (x_train, y_train) = mnist.Randomize(mnist.Train.Data, mnist.Train.Labels); | |||||
| foreach (var iteration in range(num_tr_iter)) | |||||
| { | |||||
| var start = iteration * batch_size; | |||||
| var end = (iteration + 1) * batch_size; | |||||
| var (x_batch, y_batch) = mnist.GetNextBatch(x_train, y_train, start, end); | |||||
| // Run optimization op (backprop) | |||||
| sess.run(optimizer, (x, x_batch), (y, y_batch)); | |||||
| if (iteration % display_freq == 0) | |||||
| { | |||||
| // Calculate and display the batch loss and accuracy | |||||
| (loss_val, accuracy_val) = sess.run((loss, accuracy), (x, x_batch), (y, y_batch)); | |||||
| print($"iter {iteration.ToString("000")}: Loss={loss_val.ToString("0.0000")}, Training Accuracy={accuracy_val.ToString("P")} {sw.ElapsedMilliseconds}ms"); | |||||
| sw.Restart(); | |||||
| } | |||||
| } | |||||
| // Run validation after every epoch | |||||
| (loss_val, accuracy_val) = sess.run((loss, accuracy), (x, mnist.Validation.Data), (y, mnist.Validation.Labels)); | |||||
| print("---------------------------------------------------------"); | |||||
| print($"Epoch: {epoch + 1}, validation loss: {loss_val.ToString("0.0000")}, validation accuracy: {accuracy_val.ToString("P")}"); | |||||
| print("---------------------------------------------------------"); | |||||
| } | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| (loss_test, accuracy_test) = sess.run((loss, accuracy), (x, mnist.Test.Data), (y, mnist.Test.Labels)); | |||||
| print("---------------------------------------------------------"); | |||||
| print($"Test loss: {loss_test.ToString("0.0000")}, test accuracy: {accuracy_test.ToString("P")}"); | |||||
| print("---------------------------------------------------------"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,161 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using Tensorflow; | |||||
| using Tensorflow.Hub; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Recurrent Neural Network for handwritten digits MNIST. | |||||
| /// https://medium.com/machine-learning-algorithms/mnist-using-recurrent-neural-network-2d070a5915a2 | |||||
| /// </summary> | |||||
| public class DigitRecognitionRNN : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = false; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public string Name => "MNIST RNN"; | |||||
| string logs_path = "logs"; | |||||
| // Hyper-parameters | |||||
| int n_neurons = 128; | |||||
| float learning_rate = 0.001f; | |||||
| int batch_size = 128; | |||||
| int epochs = 10; | |||||
| int n_steps = 28; | |||||
| int n_inputs = 28; | |||||
| int n_outputs = 10; | |||||
| Datasets<MnistDataSet> mnist; | |||||
| Tensor x, y; | |||||
| Tensor loss, accuracy, cls_prediction; | |||||
| Operation optimizer; | |||||
| int display_freq = 100; | |||||
| float accuracy_test = 0f; | |||||
| float loss_test = 1f; | |||||
| NDArray x_train, y_train; | |||||
| NDArray x_valid, y_valid; | |||||
| NDArray x_test, y_test; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| BuildGraph(); | |||||
| using (var sess = tf.Session()) | |||||
| { | |||||
| Train(sess); | |||||
| Test(sess); | |||||
| } | |||||
| return loss_test < 0.09 && accuracy_test > 0.95; | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| var graph = new Graph().as_default(); | |||||
| var X = tf.placeholder(tf.float32, new[] { -1, n_steps, n_inputs }); | |||||
| var y = tf.placeholder(tf.int32, new[] { -1 }); | |||||
| var cell = tf.nn.rnn_cell.BasicRNNCell(num_units: n_neurons); | |||||
| var (output, state) = tf.nn.dynamic_rnn(cell, X, dtype: tf.float32); | |||||
| return graph; | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| // Number of training iterations in each epoch | |||||
| var num_tr_iter = y_train.shape[0] / batch_size; | |||||
| var init = tf.global_variables_initializer(); | |||||
| sess.run(init); | |||||
| float loss_val = 100.0f; | |||||
| float accuracy_val = 0f; | |||||
| foreach (var epoch in range(epochs)) | |||||
| { | |||||
| print($"Training epoch: {epoch + 1}"); | |||||
| // Randomly shuffle the training data at the beginning of each epoch | |||||
| (x_train, y_train) = mnist.Randomize(x_train, y_train); | |||||
| foreach (var iteration in range(num_tr_iter)) | |||||
| { | |||||
| var start = iteration * batch_size; | |||||
| var end = (iteration + 1) * batch_size; | |||||
| var (x_batch, y_batch) = mnist.GetNextBatch(x_train, y_train, start, end); | |||||
| // Run optimization op (backprop) | |||||
| sess.run(optimizer, new FeedItem(x, x_batch), new FeedItem(y, y_batch)); | |||||
| if (iteration % display_freq == 0) | |||||
| { | |||||
| // Calculate and display the batch loss and accuracy | |||||
| var result = sess.run(new[] { loss, accuracy }, new FeedItem(x, x_batch), new FeedItem(y, y_batch)); | |||||
| loss_val = result[0]; | |||||
| accuracy_val = result[1]; | |||||
| print($"iter {iteration.ToString("000")}: Loss={loss_val.ToString("0.0000")}, Training Accuracy={accuracy_val.ToString("P")}"); | |||||
| } | |||||
| } | |||||
| // Run validation after every epoch | |||||
| var results1 = sess.run(new[] { loss, accuracy }, new FeedItem(x, x_valid), new FeedItem(y, y_valid)); | |||||
| loss_val = results1[0]; | |||||
| accuracy_val = results1[1]; | |||||
| print("---------------------------------------------------------"); | |||||
| print($"Epoch: {epoch + 1}, validation loss: {loss_val.ToString("0.0000")}, validation accuracy: {accuracy_val.ToString("P")}"); | |||||
| print("---------------------------------------------------------"); | |||||
| } | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| var result = sess.run(new[] { loss, accuracy }, new FeedItem(x, x_test), new FeedItem(y, y_test)); | |||||
| loss_test = result[0]; | |||||
| accuracy_test = result[1]; | |||||
| print("---------------------------------------------------------"); | |||||
| print($"Test loss: {loss_test.ToString("0.0000")}, test accuracy: {accuracy_test.ToString("P")}"); | |||||
| print("---------------------------------------------------------"); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| mnist = MnistModelLoader.LoadAsync(".resources/mnist", oneHot: true, showProgressInConsole: true).Result; | |||||
| (x_train, y_train) = (mnist.Train.Data, mnist.Train.Labels); | |||||
| (x_valid, y_valid) = (mnist.Validation.Data, mnist.Validation.Labels); | |||||
| (x_test, y_test) = (mnist.Test.Data, mnist.Test.Labels); | |||||
| print("Size of:"); | |||||
| print($"- Training-set:\t\t{len(mnist.Train.Data)}"); | |||||
| print($"- Validation-set:\t{len(mnist.Validation.Data)}"); | |||||
| print($"- Test-set:\t\t{len(mnist.Test.Data)}"); | |||||
| } | |||||
| public Graph ImportGraph() => throw new NotImplementedException(); | |||||
| public void Predict(Session sess) => throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| @@ -1,84 +0,0 @@ | |||||
| using System; | |||||
| using System.IO; | |||||
| using Tensorflow; | |||||
| using TensorFlowNET.Examples.Utility; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// This example removes the background from an input image. | |||||
| /// | |||||
| /// https://github.com/susheelsk/image-background-removal | |||||
| /// </summary> | |||||
| public class ImageBackgroundRemoval : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = false; | |||||
| public bool IsImportingGraph { get; set; } = true; | |||||
| public string Name => "Image Background Removal"; | |||||
| string dataDir = "deeplabv3"; | |||||
| string modelDir = "deeplabv3_mnv2_pascal_train_aug"; | |||||
| string modelName = "frozen_inference_graph.pb"; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| // import GraphDef from pb file | |||||
| var graph = new Graph().as_default(); | |||||
| graph.Import(Path.Join(dataDir, modelDir, modelName)); | |||||
| Tensor output = graph.OperationByName("SemanticPredictions"); | |||||
| using (var sess = tf.Session(graph)) | |||||
| { | |||||
| // Runs inference on a single image. | |||||
| sess.run(output, new FeedItem(output, "[np.asarray(resized_image)]")); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| // get mobile_net_model file | |||||
| string fileName = "deeplabv3_mnv2_pascal_train_aug_2018_01_29.tar.gz"; | |||||
| string url = $"http://download.tensorflow.org/models/{fileName}"; | |||||
| Web.Download(url, dataDir, fileName); | |||||
| Compress.ExtractTGZ(Path.Join(dataDir, fileName), dataDir); | |||||
| // xception_model, better accuracy | |||||
| /*fileName = "deeplabv3_pascal_train_aug_2018_01_04.tar.gz"; | |||||
| url = $"http://download.tensorflow.org/models/{fileName}"; | |||||
| Web.Download(url, modelDir, fileName); | |||||
| Compress.ExtractTGZ(Path.Join(modelDir, fileName), modelDir);*/ | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,140 +0,0 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Diagnostics; | |||||
| using System.IO; | |||||
| using Console = Colorful.Console; | |||||
| using Tensorflow; | |||||
| using System.Drawing; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Inception v3 is a widely-used image recognition model | |||||
| /// that has been shown to attain greater than 78.1% accuracy on the ImageNet dataset. | |||||
| /// The model is the culmination of many ideas developed by multiple researchers over the years. | |||||
| /// </summary> | |||||
| public class ImageRecognitionInception : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public string Name => "Image Recognition Inception"; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| string dir = "ImageRecognitionInception"; | |||||
| string pbFile = "tensorflow_inception_graph.pb"; | |||||
| string labelFile = "imagenet_comp_graph_label_strings.txt"; | |||||
| List<NDArray> file_ndarrays = new List<NDArray>(); | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| var graph = new Graph(); | |||||
| //import GraphDef from pb file | |||||
| graph.Import(Path.Join(dir, pbFile)); | |||||
| var input_name = "input"; | |||||
| var output_name = "output"; | |||||
| var input_operation = graph.OperationByName(input_name); | |||||
| var output_operation = graph.OperationByName(output_name); | |||||
| var labels = File.ReadAllLines(Path.Join(dir, labelFile)); | |||||
| var result_labels = new List<string>(); | |||||
| var sw = new Stopwatch(); | |||||
| using (var sess = tf.Session(graph)) | |||||
| { | |||||
| foreach (var nd in file_ndarrays) | |||||
| { | |||||
| sw.Restart(); | |||||
| var results = sess.run(output_operation.outputs[0], (input_operation.outputs[0], nd)); | |||||
| results = np.squeeze(results); | |||||
| int idx = np.argmax(results); | |||||
| Console.WriteLine($"{labels[idx]} {results[idx]} in {sw.ElapsedMilliseconds}ms", Color.Tan); | |||||
| result_labels.Add(labels[idx]); | |||||
| } | |||||
| } | |||||
| return result_labels.Contains("military uniform"); | |||||
| } | |||||
| private NDArray ReadTensorFromImageFile(string file_name, | |||||
| int input_height = 224, | |||||
| int input_width = 224, | |||||
| int input_mean = 117, | |||||
| int input_std = 1) | |||||
| { | |||||
| var graph = tf.Graph().as_default(); | |||||
| var file_reader = tf.read_file(file_name, "file_reader"); | |||||
| var decodeJpeg = tf.image.decode_jpeg(file_reader, channels: 3, name: "DecodeJpeg"); | |||||
| var cast = tf.cast(decodeJpeg, tf.float32); | |||||
| var dims_expander = tf.expand_dims(cast, 0); | |||||
| var resize = tf.constant(new int[] { input_height, input_width }); | |||||
| var bilinear = tf.image.resize_bilinear(dims_expander, resize); | |||||
| var sub = tf.subtract(bilinear, new float[] { input_mean }); | |||||
| var normalized = tf.divide(sub, new float[] { input_std }); | |||||
| using (var sess = tf.Session(graph)) | |||||
| return sess.run(normalized); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| Directory.CreateDirectory(dir); | |||||
| // get model file | |||||
| string url = "https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip"; | |||||
| Utility.Web.Download(url, dir, "inception5h.zip"); | |||||
| Utility.Compress.UnZip(Path.Join(dir, "inception5h.zip"), dir); | |||||
| // download sample picture | |||||
| Directory.CreateDirectory(Path.Join(dir, "img")); | |||||
| url = $"https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/examples/label_image/data/grace_hopper.jpg"; | |||||
| Utility.Web.Download(url, Path.Join(dir, "img"), "grace_hopper.jpg"); | |||||
| url = $"https://raw.githubusercontent.com/SciSharp/TensorFlow.NET/master/data/shasta-daisy.jpg"; | |||||
| Utility.Web.Download(url, Path.Join(dir, "img"), "shasta-daisy.jpg"); | |||||
| // load image file | |||||
| var files = Directory.GetFiles(Path.Join(dir, "img")); | |||||
| for (int i = 0; i < files.Length; i++) | |||||
| { | |||||
| var nd = ReadTensorFromImageFile(files[i]); | |||||
| file_ndarrays.Add(nd); | |||||
| } | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,133 +0,0 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Inception Architecture for Computer Vision | |||||
| /// Port from tensorflow\examples\label_image\label_image.py | |||||
| /// </summary> | |||||
| public class InceptionArchGoogLeNet : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = false; | |||||
| public string Name => "Inception Arch GoogLeNet"; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| string dir = "label_image_data"; | |||||
| string pbFile = "inception_v3_2016_08_28_frozen.pb"; | |||||
| string labelFile = "imagenet_slim_labels.txt"; | |||||
| string picFile = "grace_hopper.jpg"; | |||||
| int input_height = 299; | |||||
| int input_width = 299; | |||||
| int input_mean = 0; | |||||
| int input_std = 255; | |||||
| string input_name = "import/input"; | |||||
| string output_name = "import/InceptionV3/Predictions/Reshape_1"; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| var labels = File.ReadAllLines(Path.Join(dir, labelFile)); | |||||
| var nd = ReadTensorFromImageFile(Path.Join(dir, picFile), | |||||
| input_height: input_height, | |||||
| input_width: input_width, | |||||
| input_mean: input_mean, | |||||
| input_std: input_std); | |||||
| var graph = new Graph(); | |||||
| graph.Import(Path.Join(dir, pbFile)); | |||||
| var input_operation = graph.get_operation_by_name(input_name); | |||||
| var output_operation = graph.get_operation_by_name(output_name); | |||||
| NDArray results; | |||||
| using (var sess = tf.Session(graph)) | |||||
| { | |||||
| results = sess.run(output_operation.outputs[0], | |||||
| new FeedItem(input_operation.outputs[0], nd)); | |||||
| } | |||||
| results = np.squeeze(results); | |||||
| var argsort = results.argsort<float>(); | |||||
| var top_k = argsort.Data<float>() | |||||
| .Skip(results.size - 5) | |||||
| .Reverse() | |||||
| .ToArray(); | |||||
| foreach (float idx in top_k) | |||||
| Console.WriteLine($"{picFile}: {idx} {labels[(int)idx]}, {results[(int)idx]}"); | |||||
| return true; | |||||
| } | |||||
| private NDArray ReadTensorFromImageFile(string file_name, | |||||
| int input_height = 299, | |||||
| int input_width = 299, | |||||
| int input_mean = 0, | |||||
| int input_std = 255) | |||||
| { | |||||
| var graph = tf.Graph().as_default(); | |||||
| var file_reader = tf.read_file(file_name, "file_reader"); | |||||
| var image_reader = tf.image.decode_jpeg(file_reader, channels: 3, name: "jpeg_reader"); | |||||
| var caster = tf.cast(image_reader, tf.float32); | |||||
| var dims_expander = tf.expand_dims(caster, 0); | |||||
| var resize = tf.constant(new int[] { input_height, input_width }); | |||||
| var bilinear = tf.image.resize_bilinear(dims_expander, resize); | |||||
| var sub = tf.subtract(bilinear, new float[] { input_mean }); | |||||
| var normalized = tf.divide(sub, new float[] { input_std }); | |||||
| using (var sess = tf.Session(graph)) | |||||
| return sess.run(normalized); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| Directory.CreateDirectory(dir); | |||||
| // get model file | |||||
| string url = "https://storage.googleapis.com/download.tensorflow.org/models/inception_v3_2016_08_28_frozen.pb.tar.gz"; | |||||
| Utility.Web.Download(url, dir, $"{pbFile}.tar.gz"); | |||||
| Utility.Compress.ExtractTGZ(Path.Join(dir, $"{pbFile}.tar.gz"), dir); | |||||
| // download sample picture | |||||
| string pic = "grace_hopper.jpg"; | |||||
| url = $"https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/examples/label_image/data/{pic}"; | |||||
| Utility.Web.Download(url, dir, pic); | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,175 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.IO; | |||||
| using Tensorflow; | |||||
| using TensorFlowNET.Examples.Utility; | |||||
| using System.Drawing; | |||||
| using System.Drawing.Drawing2D; | |||||
| using System.Linq; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| public class ObjectDetection : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public string Name => "Object Detection"; | |||||
| public bool IsImportingGraph { get; set; } = true; | |||||
| public float MIN_SCORE = 0.5f; | |||||
| string modelDir = "ssd_mobilenet_v1_coco_2018_01_28"; | |||||
| string imageDir = "images"; | |||||
| string pbFile = "frozen_inference_graph.pb"; | |||||
| string labelFile = "mscoco_label_map.pbtxt"; | |||||
| string picFile = "input.jpg"; | |||||
| NDArray imgArr; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| // read in the input image | |||||
| imgArr = ReadTensorFromImageFile(Path.Join(imageDir, "input.jpg")); | |||||
| var graph = IsImportingGraph ? ImportGraph() : BuildGraph(); | |||||
| using (var sess = tf.Session(graph)) | |||||
| Predict(sess); | |||||
| return true; | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| var graph = new Graph().as_default(); | |||||
| graph.Import(Path.Join(modelDir, pbFile)); | |||||
| return graph; | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| var graph = tf.get_default_graph(); | |||||
| Tensor tensorNum = graph.OperationByName("num_detections"); | |||||
| Tensor tensorBoxes = graph.OperationByName("detection_boxes"); | |||||
| Tensor tensorScores = graph.OperationByName("detection_scores"); | |||||
| Tensor tensorClasses = graph.OperationByName("detection_classes"); | |||||
| Tensor imgTensor = graph.OperationByName("image_tensor"); | |||||
| Tensor[] outTensorArr = new Tensor[] { tensorNum, tensorBoxes, tensorScores, tensorClasses }; | |||||
| var results = sess.run(outTensorArr, new FeedItem(imgTensor, imgArr)); | |||||
| buildOutputImage(results); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| // get model file | |||||
| string url = "http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v1_coco_2018_01_28.tar.gz"; | |||||
| Web.Download(url, modelDir, "ssd_mobilenet_v1_coco.tar.gz"); | |||||
| Compress.ExtractTGZ(Path.Join(modelDir, "ssd_mobilenet_v1_coco.tar.gz"), "./"); | |||||
| // download sample picture | |||||
| url = $"https://github.com/tensorflow/models/raw/master/research/object_detection/test_images/image2.jpg"; | |||||
| Web.Download(url, imageDir, "input.jpg"); | |||||
| // download the pbtxt file | |||||
| url = $"https://raw.githubusercontent.com/tensorflow/models/master/research/object_detection/data/mscoco_label_map.pbtxt"; | |||||
| Web.Download(url, modelDir, "mscoco_label_map.pbtxt"); | |||||
| } | |||||
| private NDArray ReadTensorFromImageFile(string file_name) | |||||
| { | |||||
| var graph = tf.Graph().as_default(); | |||||
| var file_reader = tf.read_file(file_name, "file_reader"); | |||||
| var decodeJpeg = tf.image.decode_jpeg(file_reader, channels: 3, name: "DecodeJpeg"); | |||||
| var casted = tf.cast(decodeJpeg, TF_DataType.TF_UINT8); | |||||
| var dims_expander = tf.expand_dims(casted, 0); | |||||
| using (var sess = tf.Session(graph)) | |||||
| return sess.run(dims_expander); | |||||
| } | |||||
| private void buildOutputImage(NDArray[] resultArr) | |||||
| { | |||||
| // get pbtxt items | |||||
| PbtxtItems pbTxtItems = PbtxtParser.ParsePbtxtFile(Path.Join(modelDir, "mscoco_label_map.pbtxt")); | |||||
| // get bitmap | |||||
| Bitmap bitmap = new Bitmap(Path.Join(imageDir, "input.jpg")); | |||||
| var scores = resultArr[2].AsIterator<float>(); | |||||
| var boxes = resultArr[1].GetData<float>(); | |||||
| var id = np.squeeze(resultArr[3]).GetData<float>(); | |||||
| for (int i=0; i< scores.size; i++) | |||||
| { | |||||
| float score = scores.MoveNext(); | |||||
| if (score > MIN_SCORE) | |||||
| { | |||||
| float top = boxes[i * 4] * bitmap.Height; | |||||
| float left = boxes[i * 4 + 1] * bitmap.Width; | |||||
| float bottom = boxes[i * 4 + 2] * bitmap.Height; | |||||
| float right = boxes[i * 4 + 3] * bitmap.Width; | |||||
| Rectangle rect = new Rectangle() | |||||
| { | |||||
| X = (int)left, | |||||
| Y = (int)top, | |||||
| Width = (int)(right - left), | |||||
| Height = (int)(bottom - top) | |||||
| }; | |||||
| string name = pbTxtItems.items.Where(w => w.id == id[i]).Select(s=>s.display_name).FirstOrDefault(); | |||||
| drawObjectOnBitmap(bitmap, rect, score, name); | |||||
| } | |||||
| } | |||||
| string path = Path.Join(imageDir, "output.jpg"); | |||||
| bitmap.Save(path); | |||||
| Console.WriteLine($"Processed image is saved as {path}"); | |||||
| } | |||||
| private void drawObjectOnBitmap(Bitmap bmp, Rectangle rect, float score, string name) | |||||
| { | |||||
| using (Graphics graphic = Graphics.FromImage(bmp)) | |||||
| { | |||||
| graphic.SmoothingMode = SmoothingMode.AntiAlias; | |||||
| using (Pen pen = new Pen(Color.Red, 2)) | |||||
| { | |||||
| graphic.DrawRectangle(pen, rect); | |||||
| Point p = new Point(rect.Right + 5, rect.Top + 5); | |||||
| string text = string.Format("{0}:{1}%", name, (int)(score * 100)); | |||||
| graphic.DrawString(text, new Font("Verdana", 8), Brushes.Red, p); | |||||
| } | |||||
| } | |||||
| } | |||||
| public Graph BuildGraph() => throw new NotImplementedException(); | |||||
| public void Train(Session sess) => throw new NotImplementedException(); | |||||
| public void Test(Session sess) => throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| @@ -1,88 +0,0 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Text; | |||||
| using Tensorflow; | |||||
| using Tensorflow.Contrib.Train; | |||||
| using Tensorflow.Estimators; | |||||
| using Tensorflow.Models.ObjectDetection; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples.ImageProcessing.ObjectDetection | |||||
| { | |||||
| public class Main : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public bool IsImportingGraph { get; set; } = true; | |||||
| public string Name => "Object Detection API"; | |||||
| ModelLib model_lib = new ModelLib(); | |||||
| string model_dir = "D:/Projects/PythonLab/tf-models/research/object_detection/models/model"; | |||||
| string pipeline_config_path = "ObjectDetection/Models/faster_rcnn_resnet101_voc07.config"; | |||||
| int num_train_steps = 50; | |||||
| int sample_1_of_n_eval_examples = 1; | |||||
| int sample_1_of_n_eval_on_train_examples = 5; | |||||
| public bool Run() | |||||
| { | |||||
| var config = tf.estimator.RunConfig(model_dir: model_dir); | |||||
| var train_and_eval_dict = model_lib.create_estimator_and_inputs(run_config: config, | |||||
| hparams: new HParams(true), | |||||
| pipeline_config_path: pipeline_config_path, | |||||
| train_steps: num_train_steps, | |||||
| sample_1_of_n_eval_examples: sample_1_of_n_eval_examples, | |||||
| sample_1_of_n_eval_on_train_examples: sample_1_of_n_eval_on_train_examples); | |||||
| var estimator = train_and_eval_dict.estimator; | |||||
| var train_input_fn = train_and_eval_dict.train_input_fn; | |||||
| var eval_input_fns = train_and_eval_dict.eval_input_fns; | |||||
| var eval_on_train_input_fn = train_and_eval_dict.eval_on_train_input_fn; | |||||
| var predict_input_fn = train_and_eval_dict.predict_input_fn; | |||||
| var train_steps = train_and_eval_dict.train_steps; | |||||
| var (train_spec, eval_specs) = model_lib.create_train_and_eval_specs(train_input_fn, | |||||
| eval_input_fns, | |||||
| eval_on_train_input_fn, | |||||
| predict_input_fn, | |||||
| train_steps, | |||||
| eval_on_train_data: false); | |||||
| // Currently only a single Eval Spec is allowed. | |||||
| tf.estimator.train_and_evaluate(estimator, train_spec, eval_specs[0]); | |||||
| return true; | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| void IExample.Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,791 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using Google.Protobuf; | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Diagnostics; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using System.Threading.Tasks; | |||||
| using Tensorflow; | |||||
| using TensorFlowNET.Examples.Utility; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// In this tutorial, we will reuse the feature extraction capabilities from powerful image classifiers trained on ImageNet | |||||
| /// and simply train a new classification layer on top. Transfer learning is a technique that shortcuts much of this | |||||
| /// by taking a piece of a model that has already been trained on a related task and reusing it in a new model. | |||||
| /// | |||||
| /// https://www.tensorflow.org/hub/tutorials/image_retraining | |||||
| /// </summary> | |||||
| public class RetrainImageClassifier : IExample | |||||
| { | |||||
| public int Priority => 16; | |||||
| public bool Enabled { get; set; } = true; | |||||
| public bool IsImportingGraph { get; set; } = true; | |||||
| public string Name => "Retrain Image Classifier"; | |||||
| const string data_dir = "retrain_images"; | |||||
| string summaries_dir = Path.Join(data_dir, "retrain_logs"); | |||||
| string image_dir = Path.Join(data_dir, "flower_photos"); | |||||
| string bottleneck_dir = Path.Join(data_dir, "bottleneck"); | |||||
| string output_graph = Path.Join(data_dir, "output_graph.pb"); | |||||
| string output_labels = Path.Join(data_dir, "output_labels.txt"); | |||||
| // The location where variable checkpoints will be stored. | |||||
| string CHECKPOINT_NAME = Path.Join(data_dir, "_retrain_checkpoint"); | |||||
| string tfhub_module = "https://tfhub.dev/google/imagenet/inception_v3/feature_vector/3"; | |||||
| string input_tensor_name = "Placeholder"; | |||||
| string final_tensor_name = "Score"; | |||||
| float testing_percentage = 0.1f; | |||||
| float validation_percentage = 0.1f; | |||||
| float learning_rate = 0.01f; | |||||
| Tensor resized_image_tensor; | |||||
| Dictionary<string, Dictionary<string, string[]>> image_lists; | |||||
| int how_many_training_steps = 100; | |||||
| int eval_step_interval = 10; | |||||
| int train_batch_size = 100; | |||||
| int test_batch_size = -1; | |||||
| int validation_batch_size = 100; | |||||
| int intermediate_store_frequency = 0; | |||||
| int class_count = 0; | |||||
| const int MAX_NUM_IMAGES_PER_CLASS = 134217727; | |||||
| Operation train_step; | |||||
| Tensor final_tensor; | |||||
| Tensor bottleneck_input; | |||||
| Tensor cross_entropy; | |||||
| Tensor ground_truth_input; | |||||
| Tensor bottleneck_tensor; | |||||
| bool wants_quantization; | |||||
| float test_accuracy; | |||||
| NDArray predictions; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| #region For debug purpose | |||||
| // predict images | |||||
| // Predict(null); | |||||
| // load saved pb and test new images. | |||||
| // Test(null); | |||||
| #endregion | |||||
| var graph = IsImportingGraph ? ImportGraph() : BuildGraph(); | |||||
| using (var sess = tf.Session(graph)) | |||||
| { | |||||
| Train(sess); | |||||
| } | |||||
| return test_accuracy > 0.75f; | |||||
| } | |||||
| /// <summary> | |||||
| /// Runs a final evaluation on an eval graph using the test data set. | |||||
| /// </summary> | |||||
| /// <param name="train_session"></param> | |||||
| /// <param name="module_spec"></param> | |||||
| /// <param name="class_count"></param> | |||||
| /// <param name="image_lists"></param> | |||||
| /// <param name="jpeg_data_tensor"></param> | |||||
| /// <param name="decoded_image_tensor"></param> | |||||
| /// <param name="resized_image_tensor"></param> | |||||
| /// <param name="bottleneck_tensor"></param> | |||||
| private (float, NDArray) run_final_eval(Session train_session, object module_spec, int class_count, | |||||
| Dictionary<string, Dictionary<string, string[]>> image_lists, | |||||
| Tensor jpeg_data_tensor, Tensor decoded_image_tensor, | |||||
| Tensor resized_image_tensor, Tensor bottleneck_tensor) | |||||
| { | |||||
| var (test_bottlenecks, test_ground_truth, test_filenames) = get_random_cached_bottlenecks(train_session, image_lists, | |||||
| test_batch_size, "testing", bottleneck_dir, image_dir, jpeg_data_tensor, | |||||
| decoded_image_tensor, resized_image_tensor, bottleneck_tensor, tfhub_module); | |||||
| var (eval_session, _, bottleneck_input, ground_truth_input, evaluation_step, | |||||
| prediction) = build_eval_session(class_count); | |||||
| (float accuracy, NDArray prediction1) = eval_session.run((evaluation_step, prediction), | |||||
| (bottleneck_input, test_bottlenecks), | |||||
| (ground_truth_input, test_ground_truth)); | |||||
| print($"final test accuracy: {(accuracy * 100).ToString("G4")}% (N={len(test_bottlenecks)})"); | |||||
| return (accuracy, prediction1); | |||||
| } | |||||
| private (Session, Tensor, Tensor, Tensor, Tensor, Tensor) | |||||
| build_eval_session(int class_count) | |||||
| { | |||||
| // If quantized, we need to create the correct eval graph for exporting. | |||||
| var (eval_graph, bottleneck_tensor, resized_input_tensor, wants_quantization) = create_module_graph(); | |||||
| var eval_sess = tf.Session(graph: eval_graph); | |||||
| Tensor evaluation_step = null; | |||||
| Tensor prediction = null; | |||||
| var graph = eval_graph.as_default(); | |||||
| // Add the new layer for exporting. | |||||
| var (_, _, bottleneck_input, ground_truth_input, final_tensor) = | |||||
| add_final_retrain_ops(class_count, final_tensor_name, bottleneck_tensor, | |||||
| wants_quantization, is_training: false); | |||||
| // Now we need to restore the values from the training graph to the eval | |||||
| // graph. | |||||
| tf.train.Saver().restore(eval_sess, CHECKPOINT_NAME); | |||||
| (evaluation_step, prediction) = add_evaluation_step(final_tensor, | |||||
| ground_truth_input); | |||||
| return (eval_sess, resized_input_tensor, bottleneck_input, ground_truth_input, | |||||
| evaluation_step, prediction); | |||||
| } | |||||
| /// <summary> | |||||
| /// Adds a new softmax and fully-connected layer for training and eval. | |||||
| /// | |||||
| /// We need to retrain the top layer to identify our new classes, so this function | |||||
| /// adds the right operations to the graph, along with some variables to hold the | |||||
| /// weights, and then sets up all the gradients for the backward pass. | |||||
| /// | |||||
| /// The set up for the softmax and fully-connected layers is based on: | |||||
| /// https://www.tensorflow.org/tutorials/mnist/beginners/index.html | |||||
| /// </summary> | |||||
| /// <param name="class_count"></param> | |||||
| /// <param name="final_tensor_name"></param> | |||||
| /// <param name="bottleneck_tensor"></param> | |||||
| /// <param name="quantize_layer"></param> | |||||
| /// <param name="is_training"></param> | |||||
| /// <returns></returns> | |||||
| private (Operation, Tensor, Tensor, Tensor, Tensor) add_final_retrain_ops(int class_count, string final_tensor_name, | |||||
| Tensor bottleneck_tensor, bool quantize_layer, bool is_training) | |||||
| { | |||||
| var (batch_size, bottleneck_tensor_size) = (bottleneck_tensor.TensorShape.dims[0], bottleneck_tensor.TensorShape.dims[1]); | |||||
| tf_with(tf.name_scope("input"), scope => | |||||
| { | |||||
| bottleneck_input = tf.placeholder_with_default( | |||||
| bottleneck_tensor, | |||||
| shape: bottleneck_tensor.TensorShape.dims, | |||||
| name: "BottleneckInputPlaceholder"); | |||||
| ground_truth_input = tf.placeholder(tf.int64, new TensorShape(batch_size), name: "GroundTruthInput"); | |||||
| }); | |||||
| // Organizing the following ops so they are easier to see in TensorBoard. | |||||
| string layer_name = "final_retrain_ops"; | |||||
| Tensor logits = null; | |||||
| tf_with(tf.name_scope(layer_name), scope => | |||||
| { | |||||
| RefVariable layer_weights = null; | |||||
| tf_with(tf.name_scope("weights"), delegate | |||||
| { | |||||
| var initial_value = tf.truncated_normal(new int[] { bottleneck_tensor_size, class_count }, stddev: 0.001f); | |||||
| layer_weights = tf.Variable(initial_value, name: "final_weights"); | |||||
| variable_summaries(layer_weights); | |||||
| }); | |||||
| RefVariable layer_biases = null; | |||||
| tf_with(tf.name_scope("biases"), delegate | |||||
| { | |||||
| layer_biases = tf.Variable(tf.zeros(new TensorShape(class_count)), name: "final_biases"); | |||||
| variable_summaries(layer_biases); | |||||
| }); | |||||
| tf_with(tf.name_scope("Wx_plus_b"), delegate | |||||
| { | |||||
| logits = tf.matmul(bottleneck_input, layer_weights) + layer_biases; | |||||
| tf.summary.histogram("pre_activations", logits); | |||||
| }); | |||||
| }); | |||||
| final_tensor = tf.nn.softmax(logits, name: final_tensor_name); | |||||
| // The tf.contrib.quantize functions rewrite the graph in place for | |||||
| // quantization. The imported model graph has already been rewritten, so upon | |||||
| // calling these rewrites, only the newly added final layer will be | |||||
| // transformed. | |||||
| if (quantize_layer) | |||||
| { | |||||
| throw new NotImplementedException("quantize_layer"); | |||||
| /*if (is_training) | |||||
| tf.contrib.quantize.create_training_graph(); | |||||
| else | |||||
| tf.contrib.quantize.create_eval_graph();*/ | |||||
| } | |||||
| tf.summary.histogram("activations", final_tensor); | |||||
| // If this is an eval graph, we don't need to add loss ops or an optimizer. | |||||
| if (!is_training) | |||||
| return (null, null, bottleneck_input, ground_truth_input, final_tensor); | |||||
| Tensor cross_entropy_mean = null; | |||||
| tf_with(tf.name_scope("cross_entropy"), delegate | |||||
| { | |||||
| cross_entropy_mean = tf.losses.sparse_softmax_cross_entropy( | |||||
| labels: ground_truth_input, logits: logits); | |||||
| }); | |||||
| tf.summary.scalar("cross_entropy", cross_entropy_mean); | |||||
| tf_with(tf.name_scope("train"), delegate | |||||
| { | |||||
| var optimizer = tf.train.GradientDescentOptimizer(learning_rate); | |||||
| train_step = optimizer.minimize(cross_entropy_mean); | |||||
| }); | |||||
| return (train_step, cross_entropy_mean, bottleneck_input, ground_truth_input, | |||||
| final_tensor); | |||||
| } | |||||
| private void variable_summaries(RefVariable var) | |||||
| { | |||||
| tf_with(tf.name_scope("summaries"), delegate | |||||
| { | |||||
| var mean = tf.reduce_mean(var); | |||||
| tf.summary.scalar("mean", mean); | |||||
| Tensor stddev = null; | |||||
| tf_with(tf.name_scope("stddev"), delegate | |||||
| { | |||||
| stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean))); | |||||
| }); | |||||
| tf.summary.scalar("stddev", stddev); | |||||
| tf.summary.scalar("max", tf.reduce_max(var)); | |||||
| tf.summary.scalar("min", tf.reduce_min(var)); | |||||
| tf.summary.histogram("histogram", var); | |||||
| }); | |||||
| } | |||||
| private (Graph, Tensor, Tensor, bool) create_module_graph() | |||||
| { | |||||
| var (height, width) = (299, 299); | |||||
| var graph = tf.Graph().as_default(); | |||||
| tf.train.import_meta_graph("graph/InceptionV3.meta"); | |||||
| Tensor resized_input_tensor = graph.OperationByName(input_tensor_name); //tf.placeholder(tf.float32, new TensorShape(-1, height, width, 3)); | |||||
| // var m = hub.Module(module_spec); | |||||
| Tensor bottleneck_tensor = graph.OperationByName("module_apply_default/hub_output/feature_vector/SpatialSqueeze");// m(resized_input_tensor); | |||||
| var wants_quantization = false; | |||||
| return (graph, bottleneck_tensor, resized_input_tensor, wants_quantization); | |||||
| } | |||||
| private (NDArray, long[], string[]) get_random_cached_bottlenecks(Session sess, Dictionary<string, Dictionary<string, string[]>> image_lists, | |||||
| int how_many, string category, string bottleneck_dir, string image_dir, | |||||
| Tensor jpeg_data_tensor, Tensor decoded_image_tensor, Tensor resized_input_tensor, | |||||
| Tensor bottleneck_tensor, string module_name) | |||||
| { | |||||
| var bottlenecks = new List<float[]>(); | |||||
| var ground_truths = new List<long>(); | |||||
| var filenames = new List<string>(); | |||||
| class_count = image_lists.Keys.Count; | |||||
| if (how_many >= 0) | |||||
| { | |||||
| // Retrieve a random sample of bottlenecks. | |||||
| foreach (var unused_i in range(how_many)) | |||||
| { | |||||
| int label_index = new Random().Next(class_count); | |||||
| string label_name = image_lists.Keys.ToArray()[label_index]; | |||||
| int image_index = new Random().Next(MAX_NUM_IMAGES_PER_CLASS); | |||||
| string image_name = get_image_path(image_lists, label_name, image_index, | |||||
| image_dir, category); | |||||
| var bottleneck = get_or_create_bottleneck( | |||||
| sess, image_lists, label_name, image_index, image_dir, category, | |||||
| bottleneck_dir, jpeg_data_tensor, decoded_image_tensor, | |||||
| resized_input_tensor, bottleneck_tensor, module_name); | |||||
| bottlenecks.Add(bottleneck); | |||||
| ground_truths.Add(label_index); | |||||
| filenames.Add(image_name); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| // Retrieve all bottlenecks. | |||||
| foreach (var (label_index, label_name) in enumerate(image_lists.Keys.ToArray())) | |||||
| { | |||||
| foreach (var (image_index, image_name) in enumerate(image_lists[label_name][category])) | |||||
| { | |||||
| var bottleneck = get_or_create_bottleneck( | |||||
| sess, image_lists, label_name, image_index, image_dir, category, | |||||
| bottleneck_dir, jpeg_data_tensor, decoded_image_tensor, | |||||
| resized_input_tensor, bottleneck_tensor, module_name); | |||||
| bottlenecks.Add(bottleneck); | |||||
| ground_truths.Add(label_index); | |||||
| filenames.Add(image_name); | |||||
| } | |||||
| } | |||||
| } | |||||
| return (bottlenecks.ToArray(), ground_truths.ToArray(), filenames.ToArray()); | |||||
| } | |||||
| /// <summary> | |||||
| /// Inserts the operations we need to evaluate the accuracy of our results. | |||||
| /// </summary> | |||||
| /// <param name="result_tensor"></param> | |||||
| /// <param name="ground_truth_tensor"></param> | |||||
| /// <returns></returns> | |||||
| private (Tensor, Tensor) add_evaluation_step(Tensor result_tensor, Tensor ground_truth_tensor) | |||||
| { | |||||
| Tensor evaluation_step = null, correct_prediction = null, prediction = null; | |||||
| tf_with(tf.name_scope("accuracy"), scope => | |||||
| { | |||||
| tf_with(tf.name_scope("correct_prediction"), delegate | |||||
| { | |||||
| prediction = tf.argmax(result_tensor, 1); | |||||
| correct_prediction = tf.equal(prediction, ground_truth_tensor); | |||||
| }); | |||||
| tf_with(tf.name_scope("accuracy"), delegate | |||||
| { | |||||
| evaluation_step = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)); | |||||
| }); | |||||
| }); | |||||
| tf.summary.scalar("accuracy", evaluation_step); | |||||
| return (evaluation_step, prediction); | |||||
| } | |||||
| /// <summary> | |||||
| /// Ensures all the training, testing, and validation bottlenecks are cached. | |||||
| /// </summary> | |||||
| /// <param name="sess"></param> | |||||
| /// <param name="image_lists"></param> | |||||
| /// <param name="image_dir"></param> | |||||
| /// <param name="bottleneck_dir"></param> | |||||
| /// <param name="jpeg_data_tensor"></param> | |||||
| /// <param name="decoded_image_tensor"></param> | |||||
| /// <param name="resized_image_tensor"></param> | |||||
| /// <param name="bottleneck_tensor"></param> | |||||
| /// <param name="tfhub_module"></param> | |||||
| private void cache_bottlenecks(Session sess, Dictionary<string, Dictionary<string, string[]>> image_lists, | |||||
| string image_dir, string bottleneck_dir, Tensor jpeg_data_tensor, Tensor decoded_image_tensor, | |||||
| Tensor resized_input_tensor, Tensor bottleneck_tensor, string module_name) | |||||
| { | |||||
| int how_many_bottlenecks = 0; | |||||
| var kvs = image_lists.ToArray(); | |||||
| var categories = new string[] {"training", "testing", "validation"}; | |||||
| Parallel.For(0, kvs.Length, i => | |||||
| { | |||||
| var (label_name, label_lists) = kvs[i]; | |||||
| Parallel.For(0, categories.Length, j => | |||||
| { | |||||
| var category = categories[j]; | |||||
| var category_list = label_lists[category]; | |||||
| foreach (var (index, unused_base_name) in enumerate(category_list)) | |||||
| { | |||||
| get_or_create_bottleneck(sess, image_lists, label_name, index, image_dir, category, | |||||
| bottleneck_dir, jpeg_data_tensor, decoded_image_tensor, | |||||
| resized_input_tensor, bottleneck_tensor, module_name); | |||||
| how_many_bottlenecks++; | |||||
| if (how_many_bottlenecks % 300 == 0) | |||||
| print($"{how_many_bottlenecks} bottleneck files created."); | |||||
| } | |||||
| }); | |||||
| }); | |||||
| } | |||||
| private float[] get_or_create_bottleneck(Session sess, Dictionary<string, Dictionary<string, string[]>> image_lists, | |||||
| string label_name, int index, string image_dir, string category, string bottleneck_dir, | |||||
| Tensor jpeg_data_tensor, Tensor decoded_image_tensor, Tensor resized_input_tensor, | |||||
| Tensor bottleneck_tensor, string module_name) | |||||
| { | |||||
| var label_lists = image_lists[label_name]; | |||||
| var sub_dir_path = Path.Join(bottleneck_dir, label_name); | |||||
| Directory.CreateDirectory(sub_dir_path); | |||||
| string bottleneck_path = get_bottleneck_path(image_lists, label_name, index, | |||||
| bottleneck_dir, category, module_name); | |||||
| if (!File.Exists(bottleneck_path)) | |||||
| create_bottleneck_file(bottleneck_path, image_lists, label_name, index, | |||||
| image_dir, category, sess, jpeg_data_tensor, | |||||
| decoded_image_tensor, resized_input_tensor, | |||||
| bottleneck_tensor); | |||||
| var bottleneck_string = File.ReadAllText(bottleneck_path); | |||||
| var bottleneck_values = Array.ConvertAll(bottleneck_string.Split(','), x => float.Parse(x)); | |||||
| return bottleneck_values; | |||||
| } | |||||
| private void create_bottleneck_file(string bottleneck_path, Dictionary<string, Dictionary<string, string[]>> image_lists, | |||||
| string label_name, int index, string image_dir, string category, Session sess, | |||||
| Tensor jpeg_data_tensor, Tensor decoded_image_tensor, Tensor resized_input_tensor, Tensor bottleneck_tensor) | |||||
| { | |||||
| // Create a single bottleneck file. | |||||
| print("Creating bottleneck at " + bottleneck_path); | |||||
| var image_path = get_image_path(image_lists, label_name, index, image_dir, category); | |||||
| if (!File.Exists(image_path)) | |||||
| print($"File does not exist {image_path}"); | |||||
| var image_data = File.ReadAllBytes(image_path); | |||||
| var bottleneck_values = run_bottleneck_on_image( | |||||
| sess, image_data, jpeg_data_tensor, decoded_image_tensor, | |||||
| resized_input_tensor, bottleneck_tensor); | |||||
| var values = bottleneck_values.Data<float>(); | |||||
| var bottleneck_string = string.Join(",", values); | |||||
| File.WriteAllText(bottleneck_path, bottleneck_string); | |||||
| } | |||||
| /// <summary> | |||||
| /// Runs inference on an image to extract the 'bottleneck' summary layer. | |||||
| /// </summary> | |||||
| /// <param name="sess">Current active TensorFlow Session.</param> | |||||
| /// <param name="image_data">Data of raw JPEG data.</param> | |||||
| /// <param name="image_data_tensor">Input data layer in the graph.</param> | |||||
| /// <param name="decoded_image_tensor">Output of initial image resizing and preprocessing.</param> | |||||
| /// <param name="resized_input_tensor">The input node of the recognition graph.</param> | |||||
| /// <param name="bottleneck_tensor">Layer before the final softmax.</param> | |||||
| /// <returns></returns> | |||||
| private NDArray run_bottleneck_on_image(Session sess, byte[] image_data, Tensor image_data_tensor, | |||||
| Tensor decoded_image_tensor, Tensor resized_input_tensor, Tensor bottleneck_tensor) | |||||
| { | |||||
| // First decode the JPEG image, resize it, and rescale the pixel values. | |||||
| var resized_input_values = sess.run(decoded_image_tensor, new FeedItem(image_data_tensor, new Tensor(image_data, TF_DataType.TF_STRING))); | |||||
| // Then run it through the recognition network. | |||||
| var bottleneck_values = sess.run(bottleneck_tensor, new FeedItem(resized_input_tensor, resized_input_values))[0]; | |||||
| bottleneck_values = np.squeeze(bottleneck_values); | |||||
| return bottleneck_values; | |||||
| } | |||||
| private string get_bottleneck_path(Dictionary<string, Dictionary<string, string[]>> image_lists, string label_name, int index, | |||||
| string bottleneck_dir, string category, string module_name) | |||||
| { | |||||
| module_name = (module_name.Replace("://", "~") // URL scheme. | |||||
| .Replace('/', '~') // URL and Unix paths. | |||||
| .Replace(':', '~').Replace('\\', '~')); // Windows paths. | |||||
| return get_image_path(image_lists, label_name, index, bottleneck_dir, | |||||
| category) + "_" + module_name + ".txt"; | |||||
| } | |||||
| private string get_image_path(Dictionary<string, Dictionary<string, string[]>> image_lists, string label_name, | |||||
| int index, string image_dir, string category) | |||||
| { | |||||
| if (!image_lists.ContainsKey(label_name)) | |||||
| print($"Label does not exist {label_name}"); | |||||
| var label_lists = image_lists[label_name]; | |||||
| if (!label_lists.ContainsKey(category)) | |||||
| print($"Category does not exist {category}"); | |||||
| var category_list = label_lists[category]; | |||||
| if (category_list.Length == 0) | |||||
| print($"Label {label_name} has no images in the category {category}."); | |||||
| var mod_index = index % len(category_list); | |||||
| var base_name = category_list[mod_index].Split(Path.DirectorySeparatorChar).Last(); | |||||
| var sub_dir = label_name; | |||||
| var full_path = Path.Join(image_dir, sub_dir, base_name); | |||||
| return full_path; | |||||
| } | |||||
| /// <summary> | |||||
| /// Saves an graph to file, creating a valid quantized one if necessary. | |||||
| /// </summary> | |||||
| /// <param name="graph_file_name"></param> | |||||
| /// <param name="class_count"></param> | |||||
| private void save_graph_to_file(string graph_file_name, int class_count) | |||||
| { | |||||
| var (sess, _, _, _, _, _) = build_eval_session(class_count); | |||||
| var graph = sess.graph; | |||||
| var output_graph_def = tf.graph_util.convert_variables_to_constants( | |||||
| sess, graph.as_graph_def(), new string[] { final_tensor_name }); | |||||
| File.WriteAllBytes(graph_file_name, output_graph_def.ToByteArray()); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| // get a set of images to teach the network about the new classes | |||||
| string fileName = "flower_photos.tgz"; | |||||
| string url = $"http://download.tensorflow.org/example_images/{fileName}"; | |||||
| Web.Download(url, data_dir, fileName); | |||||
| Compress.ExtractTGZ(Path.Join(data_dir, fileName), data_dir); | |||||
| // download graph meta data | |||||
| url = "https://raw.githubusercontent.com/SciSharp/TensorFlow.NET/master/graph/InceptionV3.meta"; | |||||
| Web.Download(url, "graph", "InceptionV3.meta"); | |||||
| // download variables.data checkpoint file. | |||||
| url = "https://github.com/SciSharp/TensorFlow.NET/raw/master/data/tfhub_modules.zip"; | |||||
| Web.Download(url, data_dir, "tfhub_modules.zip"); | |||||
| Compress.UnZip(Path.Join(data_dir, "tfhub_modules.zip"), "tfhub_modules"); | |||||
| // Prepare necessary directories that can be used during training | |||||
| Directory.CreateDirectory(summaries_dir); | |||||
| Directory.CreateDirectory(bottleneck_dir); | |||||
| // Look at the folder structure, and create lists of all the images. | |||||
| image_lists = create_image_lists(); | |||||
| class_count = len(image_lists); | |||||
| if (class_count == 0) | |||||
| print($"No valid folders of images found at {image_dir}"); | |||||
| if (class_count == 1) | |||||
| print("Only one valid folder of images found at " + | |||||
| image_dir + | |||||
| " - multiple classes are needed for classification."); | |||||
| } | |||||
| private (Tensor, Tensor) add_jpeg_decoding() | |||||
| { | |||||
| // height, width, depth | |||||
| var input_dim = (299, 299, 3); | |||||
| var jpeg_data = tf.placeholder(tf.@string, name: "DecodeJPGInput"); | |||||
| var decoded_image = tf.image.decode_jpeg(jpeg_data, channels: input_dim.Item3); | |||||
| // Convert from full range of uint8 to range [0,1] of float32. | |||||
| var decoded_image_as_float = tf.image.convert_image_dtype(decoded_image, tf.float32); | |||||
| var decoded_image_4d = tf.expand_dims(decoded_image_as_float, 0); | |||||
| var resize_shape = tf.stack(new int[] { input_dim.Item1, input_dim.Item2 }); | |||||
| var resize_shape_as_int = tf.cast(resize_shape, dtype: tf.int32); | |||||
| var resized_image = tf.image.resize_bilinear(decoded_image_4d, resize_shape_as_int); | |||||
| return (jpeg_data, resized_image); | |||||
| } | |||||
| /// <summary> | |||||
| /// Builds a list of training images from the file system. | |||||
| /// </summary> | |||||
| private Dictionary<string, Dictionary<string, string[]>> create_image_lists() | |||||
| { | |||||
| var sub_dirs = tf.gfile.Walk(image_dir) | |||||
| .Select(x => x.Item1) | |||||
| .OrderBy(x => x) | |||||
| .ToArray(); | |||||
| var result = new Dictionary<string, Dictionary<string, string[]>>(); | |||||
| foreach (var sub_dir in sub_dirs) | |||||
| { | |||||
| var dir_name = sub_dir.Split(Path.DirectorySeparatorChar).Last(); | |||||
| print($"Looking for images in '{dir_name}'"); | |||||
| var file_list = Directory.GetFiles(sub_dir); | |||||
| if (len(file_list) < 20) | |||||
| print($"WARNING: Folder has less than 20 images, which may cause issues."); | |||||
| var label_name = dir_name.ToLower(); | |||||
| result[label_name] = new Dictionary<string, string[]>(); | |||||
| int testing_count = (int)Math.Floor(file_list.Length * testing_percentage); | |||||
| int validation_count = (int)Math.Floor(file_list.Length * validation_percentage); | |||||
| result[label_name]["testing"] = file_list.Take(testing_count).ToArray(); | |||||
| result[label_name]["validation"] = file_list.Skip(testing_count).Take(validation_count).ToArray(); | |||||
| result[label_name]["training"] = file_list.Skip(testing_count + validation_count).ToArray(); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| Graph graph; | |||||
| // Set up the pre-trained graph. | |||||
| (graph, bottleneck_tensor, resized_image_tensor, wants_quantization) = | |||||
| create_module_graph(); | |||||
| // Add the new layer that we'll be training. | |||||
| (train_step, cross_entropy, bottleneck_input, | |||||
| ground_truth_input, final_tensor) = add_final_retrain_ops( | |||||
| class_count, final_tensor_name, bottleneck_tensor, | |||||
| wants_quantization, is_training: true); | |||||
| return graph; | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| var sw = new Stopwatch(); | |||||
| // Initialize all weights: for the module to their pretrained values, | |||||
| // and for the newly added retraining layer to random initial values. | |||||
| var init = tf.global_variables_initializer(); | |||||
| sess.run(init); | |||||
| var (jpeg_data_tensor, decoded_image_tensor) = add_jpeg_decoding(); | |||||
| // We'll make sure we've calculated the 'bottleneck' image summaries and | |||||
| // cached them on disk. | |||||
| cache_bottlenecks(sess, image_lists, image_dir, | |||||
| bottleneck_dir, jpeg_data_tensor, | |||||
| decoded_image_tensor, resized_image_tensor, | |||||
| bottleneck_tensor, tfhub_module); | |||||
| // Create the operations we need to evaluate the accuracy of our new layer. | |||||
| var (evaluation_step, _) = add_evaluation_step(final_tensor, ground_truth_input); | |||||
| // Merge all the summaries and write them out to the summaries_dir | |||||
| var merged = tf.summary.merge_all(); | |||||
| var train_writer = tf.summary.FileWriter(summaries_dir + "/train", sess.graph); | |||||
| var validation_writer = tf.summary.FileWriter(summaries_dir + "/validation", sess.graph); | |||||
| // Create a train saver that is used to restore values into an eval graph | |||||
| // when exporting models. | |||||
| var train_saver = tf.train.Saver(); | |||||
| train_saver.save(sess, CHECKPOINT_NAME); | |||||
| sw.Restart(); | |||||
| for (int i = 0; i < how_many_training_steps; i++) | |||||
| { | |||||
| var (train_bottlenecks, train_ground_truth, _) = get_random_cached_bottlenecks( | |||||
| sess, image_lists, train_batch_size, "training", | |||||
| bottleneck_dir, image_dir, jpeg_data_tensor, | |||||
| decoded_image_tensor, resized_image_tensor, bottleneck_tensor, | |||||
| tfhub_module); | |||||
| // Feed the bottlenecks and ground truth into the graph, and run a training | |||||
| // step. Capture training summaries for TensorBoard with the `merged` op. | |||||
| var results = sess.run( | |||||
| new ITensorOrOperation[] { merged, train_step }, | |||||
| new FeedItem(bottleneck_input, train_bottlenecks), | |||||
| new FeedItem(ground_truth_input, train_ground_truth)); | |||||
| var train_summary = results[0]; | |||||
| // TODO | |||||
| // train_writer.add_summary(train_summary, i); | |||||
| // Every so often, print out how well the graph is training. | |||||
| bool is_last_step = (i + 1 == how_many_training_steps); | |||||
| if ((i % eval_step_interval) == 0 || is_last_step) | |||||
| { | |||||
| (float train_accuracy, float cross_entropy_value) = sess.run((evaluation_step, cross_entropy), | |||||
| (bottleneck_input, train_bottlenecks), | |||||
| (ground_truth_input, train_ground_truth)); | |||||
| print($"{DateTime.Now}: Step {i + 1}: Train accuracy = {train_accuracy * 100}%, Cross entropy = {cross_entropy_value.ToString("G4")}"); | |||||
| var (validation_bottlenecks, validation_ground_truth, _) = get_random_cached_bottlenecks( | |||||
| sess, image_lists, validation_batch_size, "validation", | |||||
| bottleneck_dir, image_dir, jpeg_data_tensor, | |||||
| decoded_image_tensor, resized_image_tensor, bottleneck_tensor, | |||||
| tfhub_module); | |||||
| // Run a validation step and capture training summaries for TensorBoard | |||||
| // with the `merged` op. | |||||
| (_, float validation_accuracy) = sess.run((merged, evaluation_step), | |||||
| (bottleneck_input, validation_bottlenecks), | |||||
| (ground_truth_input, validation_ground_truth)); | |||||
| // validation_writer.add_summary(validation_summary, i); | |||||
| print($"{DateTime.Now}: Step {i + 1}: Validation accuracy = {validation_accuracy * 100}% (N={len(validation_bottlenecks)}) {sw.ElapsedMilliseconds}ms"); | |||||
| sw.Restart(); | |||||
| } | |||||
| // Store intermediate results | |||||
| int intermediate_frequency = intermediate_store_frequency; | |||||
| if (intermediate_frequency > 0 && i % intermediate_frequency == 0 && i > 0) | |||||
| { | |||||
| } | |||||
| } | |||||
| // After training is complete, force one last save of the train checkpoint. | |||||
| train_saver.save(sess, CHECKPOINT_NAME); | |||||
| // We've completed all our training, so run a final test evaluation on | |||||
| // some new images we haven't used before. | |||||
| (test_accuracy, predictions) = run_final_eval(sess, null, class_count, image_lists, | |||||
| jpeg_data_tensor, decoded_image_tensor, resized_image_tensor, | |||||
| bottleneck_tensor); | |||||
| // Write out the trained graph and labels with the weights stored as | |||||
| // constants. | |||||
| print($"Save final result to : {output_graph}"); | |||||
| save_graph_to_file(output_graph, class_count); | |||||
| File.WriteAllText(output_labels, string.Join("\n", image_lists.Keys)); | |||||
| } | |||||
| /// <summary> | |||||
| /// Prediction | |||||
| /// labels mapping, it's from output_lables.txt | |||||
| /// 0 - daisy | |||||
| /// 1 - dandelion | |||||
| /// 2 - roses | |||||
| /// 3 - sunflowers | |||||
| /// 4 - tulips | |||||
| /// </summary> | |||||
| /// <param name="sess_"></param> | |||||
| public void Predict(Session sess_) | |||||
| { | |||||
| if (!File.Exists(output_graph)) | |||||
| return; | |||||
| var labels = File.ReadAllLines(output_labels); | |||||
| // predict image | |||||
| var img_path = Path.Join(image_dir, "daisy", "5547758_eea9edfd54_n.jpg"); | |||||
| var fileBytes = ReadTensorFromImageFile(img_path); | |||||
| // import graph and variables | |||||
| var graph = new Graph(); | |||||
| graph.Import(output_graph, ""); | |||||
| Tensor input = graph.OperationByName(input_tensor_name); | |||||
| Tensor output = graph.OperationByName(final_tensor_name); | |||||
| using (var sess = tf.Session(graph)) | |||||
| { | |||||
| var result = sess.run(output, (input, fileBytes)); | |||||
| var prob = np.squeeze(result); | |||||
| var idx = np.argmax(prob); | |||||
| print($"Prediction result: [{labels[idx]} {prob[idx]}] for {img_path}."); | |||||
| } | |||||
| } | |||||
| private NDArray ReadTensorFromImageFile(string file_name, | |||||
| int input_height = 299, | |||||
| int input_width = 299, | |||||
| int input_mean = 0, | |||||
| int input_std = 255) | |||||
| { | |||||
| var graph = tf.Graph().as_default(); | |||||
| var file_reader = tf.read_file(file_name, "file_reader"); | |||||
| var image_reader = tf.image.decode_jpeg(file_reader, channels: 3, name: "jpeg_reader"); | |||||
| var caster = tf.cast(image_reader, tf.float32); | |||||
| var dims_expander = tf.expand_dims(caster, 0); | |||||
| var resize = tf.constant(new int[] { input_height, input_width }); | |||||
| var bilinear = tf.image.resize_bilinear(dims_expander, resize); | |||||
| var sub = tf.subtract(bilinear, new float[] { input_mean }); | |||||
| var normalized = tf.divide(sub, new float[] { input_std }); | |||||
| using (var sess = tf.Session(graph)) | |||||
| return sess.run(normalized); | |||||
| } | |||||
| public void Test(Session sess_) | |||||
| { | |||||
| if (!File.Exists(output_graph)) | |||||
| return; | |||||
| var graph = new Graph(); | |||||
| graph.Import(output_graph); | |||||
| var (jpeg_data_tensor, decoded_image_tensor) = add_jpeg_decoding(); | |||||
| tf_with(tf.Session(graph), sess => | |||||
| { | |||||
| (test_accuracy, predictions) = run_final_eval(sess, null, class_count, image_lists, | |||||
| jpeg_data_tensor, decoded_image_tensor, resized_image_tensor, | |||||
| bottleneck_tensor); | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,54 +0,0 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Text; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples.ImageProcessing.YOLO | |||||
| { | |||||
| public class Dataset | |||||
| { | |||||
| string annot_path; | |||||
| int[] input_sizes; | |||||
| int batch_size; | |||||
| bool data_aug; | |||||
| int[] train_input_sizes; | |||||
| NDArray strides; | |||||
| NDArray anchors; | |||||
| Dictionary<int, string> classes; | |||||
| int num_classes; | |||||
| int anchor_per_scale; | |||||
| int max_bbox_per_scale; | |||||
| string[] annotations; | |||||
| int num_samples; | |||||
| int batch_count; | |||||
| public int Length = 0; | |||||
| public Dataset(string dataset_type, Config cfg) | |||||
| { | |||||
| annot_path = dataset_type == "train" ? cfg.TRAIN.ANNOT_PATH : cfg.TEST.ANNOT_PATH; | |||||
| input_sizes = dataset_type == "train" ? cfg.TRAIN.INPUT_SIZE : cfg.TEST.INPUT_SIZE; | |||||
| batch_size = dataset_type == "train" ? cfg.TRAIN.BATCH_SIZE : cfg.TEST.BATCH_SIZE; | |||||
| data_aug = dataset_type == "train" ? cfg.TRAIN.DATA_AUG : cfg.TEST.DATA_AUG; | |||||
| train_input_sizes = cfg.TRAIN.INPUT_SIZE; | |||||
| strides = np.array(cfg.YOLO.STRIDES); | |||||
| classes = Utils.read_class_names(cfg.YOLO.CLASSES); | |||||
| num_classes = classes.Count; | |||||
| anchors = np.array(Utils.get_anchors(cfg.YOLO.ANCHORS)); | |||||
| anchor_per_scale = cfg.YOLO.ANCHOR_PER_SCALE; | |||||
| max_bbox_per_scale = 150; | |||||
| annotations = load_annotations(); | |||||
| num_samples = len(annotations); | |||||
| batch_count = 0; | |||||
| } | |||||
| string[] load_annotations() | |||||
| { | |||||
| return File.ReadAllLines(annot_path); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,243 +0,0 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples.ImageProcessing.YOLO | |||||
| { | |||||
| /// <summary> | |||||
| /// Implementation of YOLO v3 object detector in Tensorflow | |||||
| /// https://github.com/YunYang1994/tensorflow-yolov3 | |||||
| /// </summary> | |||||
| public class Main : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public string Name => "YOLOv3"; | |||||
| #region args | |||||
| Dictionary<int, string> classes; | |||||
| int num_classes; | |||||
| float learn_rate_init; | |||||
| float learn_rate_end; | |||||
| int first_stage_epochs; | |||||
| int second_stage_epochs; | |||||
| int warmup_periods; | |||||
| string time; | |||||
| float moving_ave_decay; | |||||
| int max_bbox_per_scale; | |||||
| int steps_per_period; | |||||
| Dataset trainset, testset; | |||||
| Config cfg; | |||||
| Tensor input_data; | |||||
| Tensor label_sbbox; | |||||
| Tensor label_mbbox; | |||||
| Tensor label_lbbox; | |||||
| Tensor true_sbboxes; | |||||
| Tensor true_mbboxes; | |||||
| Tensor true_lbboxes; | |||||
| Tensor trainable; | |||||
| Session sess; | |||||
| YOLOv3 model; | |||||
| VariableV1[] net_var; | |||||
| Tensor giou_loss, conf_loss, prob_loss; | |||||
| RefVariable global_step; | |||||
| Tensor learn_rate; | |||||
| Tensor loss; | |||||
| List<RefVariable> first_stage_trainable_var_list; | |||||
| Operation train_op_with_frozen_variables; | |||||
| Operation train_op_with_all_variables; | |||||
| Saver loader; | |||||
| Saver saver; | |||||
| #endregion | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| var graph = IsImportingGraph ? ImportGraph() : BuildGraph(); | |||||
| var options = new SessionOptions(); | |||||
| options.SetConfig(new ConfigProto { AllowSoftPlacement = true }); | |||||
| using (var sess = tf.Session(graph, opts: options)) | |||||
| { | |||||
| Train(sess); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| sess.run(tf.global_variables_initializer()); | |||||
| print($"=> Restoring weights from: {cfg.TRAIN.INITIAL_WEIGHT} ... "); | |||||
| loader.restore(sess, cfg.TRAIN.INITIAL_WEIGHT); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| var graph = new Graph().as_default(); | |||||
| tf_with(tf.name_scope("define_input"), scope => | |||||
| { | |||||
| input_data = tf.placeholder(dtype: tf.float32, name: "input_data"); | |||||
| label_sbbox = tf.placeholder(dtype: tf.float32, name: "label_sbbox"); | |||||
| label_mbbox = tf.placeholder(dtype: tf.float32, name: "label_mbbox"); | |||||
| label_lbbox = tf.placeholder(dtype: tf.float32, name: "label_lbbox"); | |||||
| true_sbboxes = tf.placeholder(dtype: tf.float32, name: "sbboxes"); | |||||
| true_mbboxes = tf.placeholder(dtype: tf.float32, name: "mbboxes"); | |||||
| true_lbboxes = tf.placeholder(dtype: tf.float32, name: "lbboxes"); | |||||
| trainable = tf.placeholder(dtype: tf.@bool, name: "training"); | |||||
| }); | |||||
| tf_with(tf.name_scope("define_loss"), scope => | |||||
| { | |||||
| model = new YOLOv3(cfg, input_data, trainable); | |||||
| net_var = tf.global_variables(); | |||||
| (giou_loss, conf_loss, prob_loss) = model.compute_loss( | |||||
| label_sbbox, label_mbbox, label_lbbox, | |||||
| true_sbboxes, true_mbboxes, true_lbboxes); | |||||
| loss = giou_loss + conf_loss + prob_loss; | |||||
| }); | |||||
| Tensor global_step_update = null; | |||||
| tf_with(tf.name_scope("learn_rate"), scope => | |||||
| { | |||||
| global_step = tf.Variable(1.0, dtype: tf.float64, trainable: false, name: "global_step"); | |||||
| var warmup_steps = tf.constant(warmup_periods * steps_per_period, | |||||
| dtype: tf.float64, name: "warmup_steps"); | |||||
| var train_steps = tf.constant((first_stage_epochs + second_stage_epochs) * steps_per_period, | |||||
| dtype: tf.float64, name: "train_steps"); | |||||
| learn_rate = tf.cond( | |||||
| pred: global_step < warmup_steps, | |||||
| true_fn: delegate | |||||
| { | |||||
| return global_step / warmup_steps * learn_rate_init; | |||||
| }, | |||||
| false_fn: delegate | |||||
| { | |||||
| return learn_rate_end + 0.5 * (learn_rate_init - learn_rate_end) * | |||||
| (1 + tf.cos( | |||||
| (global_step - warmup_steps) / (train_steps - warmup_steps) * Math.PI)); | |||||
| } | |||||
| ); | |||||
| global_step_update = tf.assign_add(global_step, 1.0f); | |||||
| }); | |||||
| Operation moving_ave = null; | |||||
| tf_with(tf.name_scope("define_weight_decay"), scope => | |||||
| { | |||||
| var emv = tf.train.ExponentialMovingAverage(moving_ave_decay); | |||||
| var vars = tf.trainable_variables().Select(x => (RefVariable)x).ToArray(); | |||||
| moving_ave = emv.apply(vars); | |||||
| }); | |||||
| tf_with(tf.name_scope("define_first_stage_train"), scope => | |||||
| { | |||||
| first_stage_trainable_var_list = new List<RefVariable>(); | |||||
| foreach (var var in tf.trainable_variables()) | |||||
| { | |||||
| var var_name = var.op.name; | |||||
| var var_name_mess = var_name.Split('/'); | |||||
| if (new[] { "conv_sbbox", "conv_mbbox", "conv_lbbox" }.Contains(var_name_mess[0])) | |||||
| first_stage_trainable_var_list.Add(var as RefVariable); | |||||
| } | |||||
| var adam = tf.train.AdamOptimizer(learn_rate); | |||||
| var first_stage_optimizer = adam.minimize(loss, var_list: first_stage_trainable_var_list); | |||||
| tf_with(tf.control_dependencies(tf.get_collection<Operation>(tf.GraphKeys.UPDATE_OPS).ToArray()), delegate | |||||
| { | |||||
| tf_with(tf.control_dependencies(new ITensorOrOperation[] { first_stage_optimizer, global_step_update }), delegate | |||||
| { | |||||
| tf_with(tf.control_dependencies(new[] { moving_ave }), delegate | |||||
| { | |||||
| train_op_with_frozen_variables = tf.no_op(); | |||||
| }); | |||||
| }); | |||||
| }); | |||||
| }); | |||||
| tf_with(tf.name_scope("define_second_stage_train"), delegate | |||||
| { | |||||
| var second_stage_trainable_var_list = tf.trainable_variables().Select(x => x as RefVariable).ToList(); | |||||
| var adam = tf.train.AdamOptimizer(learn_rate); | |||||
| var second_stage_optimizer = adam.minimize(loss, var_list: second_stage_trainable_var_list); | |||||
| tf_with(tf.control_dependencies(tf.get_collection<Operation>(tf.GraphKeys.UPDATE_OPS).ToArray()), delegate | |||||
| { | |||||
| tf_with(tf.control_dependencies(new ITensorOrOperation[] { second_stage_optimizer, global_step_update }), delegate | |||||
| { | |||||
| tf_with(tf.control_dependencies(new[] { moving_ave }), delegate | |||||
| { | |||||
| train_op_with_all_variables = tf.no_op(); | |||||
| }); | |||||
| }); | |||||
| }); | |||||
| }); | |||||
| tf_with(tf.name_scope("loader_and_saver"), delegate | |||||
| { | |||||
| loader = tf.train.Saver(net_var); | |||||
| saver = tf.train.Saver(tf.global_variables(), max_to_keep: 10); | |||||
| }); | |||||
| tf_with(tf.name_scope("summary"), delegate | |||||
| { | |||||
| tf.summary.scalar("learn_rate", learn_rate); | |||||
| tf.summary.scalar("giou_loss", giou_loss); | |||||
| tf.summary.scalar("conf_loss", conf_loss); | |||||
| tf.summary.scalar("prob_loss", prob_loss); | |||||
| tf.summary.scalar("total_loss", loss); | |||||
| }); | |||||
| return graph; | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| cfg = new Config(Name); | |||||
| string dataDir = Path.Combine(Name, "data"); | |||||
| Directory.CreateDirectory(dataDir); | |||||
| classes = Utils.read_class_names(cfg.YOLO.CLASSES); | |||||
| num_classes = classes.Count; | |||||
| learn_rate_init = cfg.TRAIN.LEARN_RATE_INIT; | |||||
| learn_rate_end = cfg.TRAIN.LEARN_RATE_END; | |||||
| first_stage_epochs = cfg.TRAIN.FISRT_STAGE_EPOCHS; | |||||
| second_stage_epochs = cfg.TRAIN.SECOND_STAGE_EPOCHS; | |||||
| warmup_periods = cfg.TRAIN.WARMUP_EPOCHS; | |||||
| DateTime now = DateTime.Now; | |||||
| time = $"{now.Year}-{now.Month}-{now.Day}-{now.Hour}-{now.Minute}-{now.Minute}"; | |||||
| moving_ave_decay = cfg.YOLO.MOVING_AVE_DECAY; | |||||
| max_bbox_per_scale = 150; | |||||
| trainset = new Dataset("train", cfg); | |||||
| testset = new Dataset("test", cfg); | |||||
| steps_per_period = trainset.Length; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,27 +0,0 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| namespace TensorFlowNET.Examples.ImageProcessing.YOLO | |||||
| { | |||||
| class Utils | |||||
| { | |||||
| public static Dictionary<int, string> read_class_names(string file) | |||||
| { | |||||
| var classes = new Dictionary<int, string>(); | |||||
| foreach (var line in File.ReadAllLines(file)) | |||||
| classes[classes.Count] = line; | |||||
| return classes; | |||||
| } | |||||
| public static NDArray get_anchors(string file) | |||||
| { | |||||
| return np.array(File.ReadAllText(file).Split(',') | |||||
| .Select(x => float.Parse(x)) | |||||
| .ToArray()).reshape(3, 3, 2); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,291 +0,0 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples.ImageProcessing.YOLO | |||||
| { | |||||
| public class YOLOv3 | |||||
| { | |||||
| Config cfg; | |||||
| Tensor trainable; | |||||
| Tensor input_data; | |||||
| Dictionary<int, string> classes; | |||||
| int num_class; | |||||
| NDArray strides; | |||||
| NDArray anchors; | |||||
| int anchor_per_scale; | |||||
| float iou_loss_thresh; | |||||
| string upsample_method; | |||||
| Tensor conv_lbbox; | |||||
| Tensor conv_mbbox; | |||||
| Tensor conv_sbbox; | |||||
| Tensor pred_sbbox; | |||||
| Tensor pred_mbbox; | |||||
| Tensor pred_lbbox; | |||||
| public YOLOv3(Config cfg_, Tensor input_data_, Tensor trainable_) | |||||
| { | |||||
| cfg = cfg_; | |||||
| input_data = input_data_; | |||||
| trainable = trainable_; | |||||
| classes = Utils.read_class_names(cfg.YOLO.CLASSES); | |||||
| num_class = len(classes); | |||||
| strides = np.array(cfg.YOLO.STRIDES); | |||||
| anchors = Utils.get_anchors(cfg.YOLO.ANCHORS); | |||||
| anchor_per_scale = cfg.YOLO.ANCHOR_PER_SCALE; | |||||
| iou_loss_thresh = cfg.YOLO.IOU_LOSS_THRESH; | |||||
| upsample_method = cfg.YOLO.UPSAMPLE_METHOD; | |||||
| (conv_lbbox, conv_mbbox, conv_sbbox) = __build_nework(input_data); | |||||
| tf_with(tf.variable_scope("pred_sbbox"), scope => | |||||
| { | |||||
| pred_sbbox = decode(conv_sbbox, anchors[0], strides[0]); | |||||
| }); | |||||
| tf_with(tf.variable_scope("pred_mbbox"), scope => | |||||
| { | |||||
| pred_mbbox = decode(conv_mbbox, anchors[1], strides[1]); | |||||
| }); | |||||
| tf_with(tf.variable_scope("pred_lbbox"), scope => | |||||
| { | |||||
| pred_lbbox = decode(conv_lbbox, anchors[2], strides[2]); | |||||
| }); | |||||
| } | |||||
| private (Tensor, Tensor, Tensor) __build_nework(Tensor input_data) | |||||
| { | |||||
| Tensor route_1, route_2; | |||||
| (route_1, route_2, input_data) = backbone.darknet53(input_data, trainable); | |||||
| input_data = common.convolutional(input_data, new[] { 1, 1, 1024, 512 }, trainable, "conv52"); | |||||
| input_data = common.convolutional(input_data, new[] { 3, 3, 512, 1024 }, trainable, "conv53"); | |||||
| input_data = common.convolutional(input_data, new[] { 1, 1, 1024, 512 }, trainable, "conv54"); | |||||
| input_data = common.convolutional(input_data, new[] { 3, 3, 512, 1024 }, trainable, "conv55"); | |||||
| input_data = common.convolutional(input_data, new[] { 1, 1, 1024, 512 }, trainable, "conv56"); | |||||
| var conv_lobj_branch = common.convolutional(input_data, new[] { 3, 3, 512, 1024 }, trainable, name: "conv_lobj_branch"); | |||||
| var conv_lbbox = common.convolutional(conv_lobj_branch, new[] { 1, 1, 1024, 3 * (num_class + 5) }, | |||||
| trainable: trainable, name: "conv_lbbox", activate: false, bn: false); | |||||
| input_data = common.convolutional(input_data, new[] { 1, 1, 512, 256 }, trainable, "conv57"); | |||||
| input_data = common.upsample(input_data, name: "upsample0", method: upsample_method); | |||||
| tf_with(tf.variable_scope("route_1"), delegate | |||||
| { | |||||
| input_data = tf.concat(new[] { input_data, route_2 }, axis: -1); | |||||
| }); | |||||
| input_data = common.convolutional(input_data, new[] { 1, 1, 768, 256 }, trainable, "conv58"); | |||||
| input_data = common.convolutional(input_data, new[] { 3, 3, 256, 512 }, trainable, "conv59"); | |||||
| input_data = common.convolutional(input_data, new[] { 1, 1, 512, 256 }, trainable, "conv60"); | |||||
| input_data = common.convolutional(input_data, new[] { 3, 3, 256, 512 }, trainable, "conv61"); | |||||
| input_data = common.convolutional(input_data, new[] { 1, 1, 512, 256 }, trainable, "conv62"); | |||||
| var conv_mobj_branch = common.convolutional(input_data, new[] { 3, 3, 256, 512 }, trainable, name: "conv_mobj_branch"); | |||||
| conv_mbbox = common.convolutional(conv_mobj_branch, new[] { 1, 1, 512, 3 * (num_class + 5) }, | |||||
| trainable: trainable, name: "conv_mbbox", activate: false, bn: false); | |||||
| input_data = common.convolutional(input_data, new[] { 1, 1, 256, 128 }, trainable, "conv63"); | |||||
| input_data = common.upsample(input_data, name: "upsample1", method: upsample_method); | |||||
| tf_with(tf.variable_scope("route_2"), delegate | |||||
| { | |||||
| input_data = tf.concat(new[] { input_data, route_1 }, axis: -1); | |||||
| }); | |||||
| input_data = common.convolutional(input_data, new[] { 1, 1, 384, 128 }, trainable, "conv64"); | |||||
| input_data = common.convolutional(input_data, new[] { 3, 3, 128, 256 }, trainable, "conv65"); | |||||
| input_data = common.convolutional(input_data, new[] { 1, 1, 256, 128 }, trainable, "conv66"); | |||||
| input_data = common.convolutional(input_data, new[] { 3, 3, 128, 256 }, trainable, "conv67"); | |||||
| input_data = common.convolutional(input_data, new[] { 1, 1, 256, 128 }, trainable, "conv68"); | |||||
| var conv_sobj_branch = common.convolutional(input_data, new[] { 3, 3, 128, 256 }, trainable, name: "conv_sobj_branch"); | |||||
| conv_sbbox = common.convolutional(conv_sobj_branch, new[] { 1, 1, 256, 3 * (num_class + 5) }, | |||||
| trainable: trainable, name: "conv_sbbox", activate: false, bn: false); | |||||
| return (conv_lbbox, conv_mbbox, conv_sbbox); | |||||
| } | |||||
| private Tensor decode(Tensor conv_output, NDArray anchors, int stride) | |||||
| { | |||||
| var conv_shape = tf.shape(conv_output); | |||||
| var batch_size = conv_shape[0]; | |||||
| var output_size = conv_shape[1]; | |||||
| anchor_per_scale = len(anchors); | |||||
| conv_output = tf.reshape(conv_output, new object[] { batch_size, output_size, output_size, anchor_per_scale, 5 + num_class }); | |||||
| var conv_raw_dxdy = conv_output[":", ":", ":", ":", "0:2"]; | |||||
| var conv_raw_dwdh = conv_output[":", ":", ":", ":", "2:4"]; | |||||
| var conv_raw_conf = conv_output[":", ":", ":", ":", "4:5"]; | |||||
| var conv_raw_prob = conv_output[":", ":", ":", ":", "5:"]; | |||||
| var y = tf.tile(tf.range(output_size, dtype: tf.int32)[":", tf.newaxis], new object[] { 1, output_size }); | |||||
| var x = tf.tile(tf.range(output_size, dtype: tf.int32)[tf.newaxis, ":"], new object[] { output_size, 1 }); | |||||
| var xy_grid = tf.concat(new[] { x[":", ":", tf.newaxis], y[":", ":", tf.newaxis] }, axis: -1); | |||||
| xy_grid = tf.tile(xy_grid[tf.newaxis, ":", ":", tf.newaxis, ":"], new object[] { batch_size, 1, 1, anchor_per_scale, 1 }); | |||||
| xy_grid = tf.cast(xy_grid, tf.float32); | |||||
| var pred_xy = (tf.sigmoid(conv_raw_dxdy) + xy_grid) * stride; | |||||
| var pred_wh = (tf.exp(conv_raw_dwdh) * anchors) * stride; | |||||
| var pred_xywh = tf.concat(new[] { pred_xy, pred_wh }, axis: -1); | |||||
| var pred_conf = tf.sigmoid(conv_raw_conf); | |||||
| var pred_prob = tf.sigmoid(conv_raw_prob); | |||||
| return tf.concat(new[] { pred_xywh, pred_conf, pred_prob }, axis: -1); | |||||
| } | |||||
| public (Tensor, Tensor, Tensor) compute_loss(Tensor label_sbbox, Tensor label_mbbox, Tensor label_lbbox, | |||||
| Tensor true_sbbox, Tensor true_mbbox, Tensor true_lbbox) | |||||
| { | |||||
| Tensor giou_loss = null, conf_loss = null, prob_loss = null; | |||||
| (Tensor, Tensor, Tensor) loss_sbbox = (null, null, null); | |||||
| (Tensor, Tensor, Tensor) loss_mbbox = (null, null, null); | |||||
| (Tensor, Tensor, Tensor) loss_lbbox = (null, null, null); | |||||
| tf_with(tf.name_scope("smaller_box_loss"), delegate | |||||
| { | |||||
| loss_sbbox = loss_layer(conv_sbbox, pred_sbbox, label_sbbox, true_sbbox, | |||||
| anchors: anchors[0], stride: strides[0]); | |||||
| }); | |||||
| tf_with(tf.name_scope("medium_box_loss"), delegate | |||||
| { | |||||
| loss_mbbox = loss_layer(conv_mbbox, pred_mbbox, label_mbbox, true_mbbox, | |||||
| anchors: anchors[1], stride: strides[1]); | |||||
| }); | |||||
| tf_with(tf.name_scope("bigger_box_loss"), delegate | |||||
| { | |||||
| loss_lbbox = loss_layer(conv_lbbox, pred_lbbox, label_lbbox, true_lbbox, | |||||
| anchors: anchors[2], stride: strides[2]); | |||||
| }); | |||||
| tf_with(tf.name_scope("giou_loss"), delegate | |||||
| { | |||||
| giou_loss = loss_sbbox.Item1 + loss_mbbox.Item1 + loss_lbbox.Item1; | |||||
| }); | |||||
| tf_with(tf.name_scope("conf_loss"), delegate | |||||
| { | |||||
| conf_loss = loss_sbbox.Item2 + loss_mbbox.Item2 + loss_lbbox.Item2; | |||||
| }); | |||||
| tf_with(tf.name_scope("prob_loss"), delegate | |||||
| { | |||||
| prob_loss = loss_sbbox.Item3 + loss_mbbox.Item3 + loss_lbbox.Item3; | |||||
| }); | |||||
| return (giou_loss, conf_loss, prob_loss); | |||||
| } | |||||
| public (Tensor, Tensor, Tensor) loss_layer(Tensor conv, Tensor pred, Tensor label, Tensor bboxes, NDArray anchors, int stride) | |||||
| { | |||||
| var conv_shape = tf.shape(conv); | |||||
| var batch_size = conv_shape[0]; | |||||
| var output_size = conv_shape[1]; | |||||
| var input_size = stride * output_size; | |||||
| conv = tf.reshape(conv, new object[] {batch_size, output_size, output_size, | |||||
| anchor_per_scale, 5 + num_class }); | |||||
| var conv_raw_conf = conv[":", ":", ":", ":", "4:5"]; | |||||
| var conv_raw_prob = conv[":", ":", ":", ":", "5:"]; | |||||
| var pred_xywh = pred[":", ":", ":", ":", "0:4"]; | |||||
| var pred_conf = pred[":", ":", ":", ":", "4:5"]; | |||||
| var label_xywh = label[":", ":", ":", ":", "0:4"]; | |||||
| var respond_bbox = label[":", ":", ":", ":", "4:5"]; | |||||
| var label_prob = label[":", ":", ":", ":", "5:"]; | |||||
| var giou = tf.expand_dims(bbox_giou(pred_xywh, label_xywh), axis: -1); | |||||
| input_size = tf.cast(input_size, tf.float32); | |||||
| var bbox_loss_scale = 2.0 - 1.0 * label_xywh[":", ":", ":", ":", "2:3"] * label_xywh[":", ":", ":", ":", "3:4"] / (tf.sqrt(input_size)); | |||||
| var giou_loss = respond_bbox * bbox_loss_scale * (1 - giou); | |||||
| var iou = bbox_iou(pred_xywh[":", ":", ":", ":", tf.newaxis, ":"], bboxes[":", tf.newaxis, tf.newaxis, tf.newaxis, ":", ":"]); | |||||
| var max_iou = tf.expand_dims(tf.reduce_max(iou, axis: new[] { -1 }), axis: -1); | |||||
| var respond_bgd = (1.0 - respond_bbox) * tf.cast(max_iou < iou_loss_thresh, tf.float32); | |||||
| var conf_focal = focal(respond_bbox, pred_conf); | |||||
| var conf_loss = conf_focal * ( | |||||
| respond_bbox * tf.nn.sigmoid_cross_entropy_with_logits(labels: respond_bbox, logits: conv_raw_conf) + | |||||
| respond_bgd * tf.nn.sigmoid_cross_entropy_with_logits(labels: respond_bbox, logits: conv_raw_conf)); | |||||
| var prob_loss = respond_bbox * tf.nn.sigmoid_cross_entropy_with_logits(labels: label_prob, logits: conv_raw_prob); | |||||
| giou_loss = tf.reduce_mean(tf.reduce_sum(giou_loss, axis: new[] { 1, 2, 3, 4 })); | |||||
| conf_loss = tf.reduce_mean(tf.reduce_sum(conf_loss, axis: new[] { 1, 2, 3, 4 })); | |||||
| prob_loss = tf.reduce_mean(tf.reduce_sum(prob_loss, axis: new[] { 1, 2, 3, 4 })); | |||||
| return (giou_loss, conf_loss, prob_loss); | |||||
| } | |||||
| public Tensor focal(Tensor target, Tensor actual, int alpha = 1, int gamma = 2) | |||||
| { | |||||
| var focal_loss = alpha * tf.pow(tf.abs(target - actual), gamma); | |||||
| return focal_loss; | |||||
| } | |||||
| public Tensor bbox_giou(Tensor boxes1, Tensor boxes2) | |||||
| { | |||||
| boxes1 = tf.concat(new[] { boxes1["...", ":2"] - boxes1["...", "2:"] * 0.5, | |||||
| boxes1["...", ":2"] + boxes1["...", "2:"] * 0.5}, axis: -1); | |||||
| boxes2 = tf.concat(new[] { boxes2["...", ":2"] - boxes2["...", "2:"] * 0.5, | |||||
| boxes2["...", ":2"] + boxes2["...", "2:"] * 0.5}, axis: -1); | |||||
| boxes1 = tf.concat(new[] { tf.minimum(boxes1["...", ":2"], boxes1["...", "2:"]), | |||||
| tf.maximum(boxes1["...", ":2"], boxes1["...", "2:"])}, axis: -1); | |||||
| boxes2 = tf.concat(new[] { tf.minimum(boxes2["...", ":2"], boxes2["...", "2:"]), | |||||
| tf.maximum(boxes2["...", ":2"], boxes2["...", "2:"])}, axis: -1); | |||||
| var boxes1_area = (boxes1["...", "2"] - boxes1["...", "0"]) * (boxes1["...", "3"] - boxes1["...", "1"]); | |||||
| var boxes2_area = (boxes2["...", "2"] - boxes2["...", "0"]) * (boxes2["...", "3"] - boxes2["...", "1"]); | |||||
| var left_up = tf.maximum(boxes1["...", ":2"], boxes2["...", ":2"]); | |||||
| var right_down = tf.minimum(boxes1["...", "2:"], boxes2["...", "2:"]); | |||||
| var inter_section = tf.maximum(right_down - left_up, 0.0f); | |||||
| var inter_area = inter_section["...", "0"] * inter_section["...", "1"]; | |||||
| var union_area = boxes1_area + boxes2_area - inter_area; | |||||
| var iou = inter_area / union_area; | |||||
| var enclose_left_up = tf.minimum(boxes1["...", ":2"], boxes2["...", ":2"]); | |||||
| var enclose_right_down = tf.maximum(boxes1["...", "2:"], boxes2["...", "2:"]); | |||||
| var enclose = tf.maximum(enclose_right_down - enclose_left_up, 0.0); | |||||
| var enclose_area = enclose["...", "0"] * enclose["...", "1"]; | |||||
| var giou = iou - 1.0 * (enclose_area - union_area) / enclose_area; | |||||
| return giou; | |||||
| } | |||||
| public Tensor bbox_iou(Tensor boxes1, Tensor boxes2) | |||||
| { | |||||
| var boxes1_area = boxes1["...", "2"] * boxes1["...", "3"]; | |||||
| var boxes2_area = boxes2["...", "2"] * boxes2["...", "3"]; | |||||
| boxes1 = tf.concat(new[] { boxes1["...", ":2"] - boxes1["...", "2:"] * 0.5, | |||||
| boxes1["...", ":2"] + boxes1["...", "2:"] * 0.5}, axis: -1); | |||||
| boxes2 = tf.concat(new[] { boxes2["...", ":2"] - boxes2["...", "2:"] * 0.5, | |||||
| boxes2["...", ":2"] + boxes2["...", "2:"] * 0.5}, axis: -1); | |||||
| var left_up = tf.maximum(boxes1["...", ":2"], boxes2["...", ":2"]); | |||||
| var right_down = tf.minimum(boxes1["...", "2:"], boxes2["...", "2:"]); | |||||
| var inter_section = tf.maximum(right_down - left_up, 0.0); | |||||
| var inter_area = inter_section["...", "0"] * inter_section["...", "1"]; | |||||
| var union_area = boxes1_area + boxes2_area - inter_area; | |||||
| var iou = 1.0 * inter_area / union_area; | |||||
| return iou; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,51 +0,0 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples.ImageProcessing.YOLO | |||||
| { | |||||
| class backbone | |||||
| { | |||||
| public static (Tensor, Tensor, Tensor) darknet53(Tensor input_data, Tensor trainable) | |||||
| { | |||||
| return tf_with(tf.variable_scope("darknet"), scope => | |||||
| { | |||||
| input_data = common.convolutional(input_data, filters_shape: new int[] { 3, 3, 3, 32 }, trainable: trainable, name: "conv0"); | |||||
| input_data = common.convolutional(input_data, filters_shape: new int[] { 3, 3, 32, 64 }, trainable: trainable, name: "conv1", downsample: true); | |||||
| foreach (var i in range(1)) | |||||
| input_data = common.residual_block(input_data, 64, 32, 64, trainable: trainable, name: $"residual{i + 0}"); | |||||
| input_data = common.convolutional(input_data, filters_shape: new[] { 3, 3, 64, 128 }, | |||||
| trainable: trainable, name: "conv4", downsample: true); | |||||
| foreach (var i in range(2)) | |||||
| input_data = common.residual_block(input_data, 128, 64, 128, trainable: trainable, name: $"residual{i + 1}"); | |||||
| input_data = common.convolutional(input_data, filters_shape: new[] { 3, 3, 128, 256 }, | |||||
| trainable: trainable, name: "conv9", downsample: true); | |||||
| foreach (var i in range(8)) | |||||
| input_data = common.residual_block(input_data, 256, 128, 256, trainable: trainable, name: $"residual{i + 3}"); | |||||
| var route_1 = input_data; | |||||
| input_data = common.convolutional(input_data, filters_shape: new int[] { 3, 3, 256, 512 }, | |||||
| trainable: trainable, name: "conv26", downsample: true); | |||||
| foreach (var i in range(8)) | |||||
| input_data = common.residual_block(input_data, 512, 256, 512, trainable: trainable, name: $"residual{i + 11}"); | |||||
| var route_2 = input_data; | |||||
| input_data = common.convolutional(input_data, filters_shape: new[] { 3, 3, 512, 1024 }, | |||||
| trainable: trainable, name: "conv43", downsample: true); | |||||
| foreach (var i in range(4)) | |||||
| input_data = common.residual_block(input_data, 1024, 512, 1024, trainable: trainable, name: $"residual{i + 19}"); | |||||
| return (route_1, route_2, input_data); | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,100 +0,0 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Diagnostics; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples.ImageProcessing.YOLO | |||||
| { | |||||
| class common | |||||
| { | |||||
| public static Tensor convolutional(Tensor input_data, int[] filters_shape, Tensor trainable, | |||||
| string name, bool downsample = false, bool activate = true, | |||||
| bool bn = true) | |||||
| { | |||||
| return tf_with(tf.variable_scope(name), scope => | |||||
| { | |||||
| int[] strides; | |||||
| string padding; | |||||
| if (downsample) | |||||
| { | |||||
| (int pad_h, int pad_w) = ((int)Math.Floor((filters_shape[0] - 2) / 2.0f) + 1, (int)Math.Floor((filters_shape[1] - 2) / 2.0f) + 1); | |||||
| var paddings = tf.constant(new int[,] { { 0, 0 }, { pad_h, pad_h }, { pad_w, pad_w }, { 0, 0 } }); | |||||
| input_data = tf.pad(input_data, paddings, "CONSTANT"); | |||||
| strides = new[] { 1, 2, 2, 1 }; | |||||
| padding = "VALID"; | |||||
| } | |||||
| else | |||||
| { | |||||
| strides = new int[] { 1, 1, 1, 1 }; | |||||
| padding = "SAME"; | |||||
| } | |||||
| var weight = tf.get_variable(name: "weight", dtype: tf.float32, trainable: true, | |||||
| shape: filters_shape, initializer: tf.random_normal_initializer(stddev: 0.01f)); | |||||
| var conv = tf.nn.conv2d(input: input_data, filter: weight, strides: strides, padding: padding); | |||||
| if (bn) | |||||
| { | |||||
| conv = tf.layers.batch_normalization(conv, beta_initializer: tf.zeros_initializer, | |||||
| gamma_initializer: tf.ones_initializer, | |||||
| moving_mean_initializer: tf.zeros_initializer, | |||||
| moving_variance_initializer: tf.ones_initializer, training: trainable); | |||||
| } | |||||
| else | |||||
| { | |||||
| var bias = tf.get_variable(name: "bias", shape: filters_shape.Last(), trainable: true, | |||||
| dtype: tf.float32, initializer: tf.constant_initializer(0.0f)); | |||||
| conv = tf.nn.bias_add(conv, bias); | |||||
| } | |||||
| if (activate) | |||||
| conv = tf.nn.leaky_relu(conv, alpha: 0.1f); | |||||
| return conv; | |||||
| }); | |||||
| } | |||||
| public static Tensor upsample(Tensor input_data, string name, string method = "deconv") | |||||
| { | |||||
| Debug.Assert(new[] { "resize", "deconv" }.Contains(method)); | |||||
| Tensor output = null; | |||||
| if (method == "resize") | |||||
| { | |||||
| tf_with(tf.variable_scope(name), delegate | |||||
| { | |||||
| var input_shape = tf.shape(input_data); | |||||
| output = tf.image.resize_nearest_neighbor(input_data, new Tensor[] { input_shape[1] * 2, input_shape[2] * 2 }); | |||||
| }); | |||||
| } | |||||
| else if(method == "deconv") | |||||
| { | |||||
| throw new NotImplementedException("upsample.deconv"); | |||||
| } | |||||
| return output; | |||||
| } | |||||
| public static Tensor residual_block(Tensor input_data, int input_channel, int filter_num1, | |||||
| int filter_num2, Tensor trainable, string name) | |||||
| { | |||||
| var short_cut = input_data; | |||||
| return tf_with(tf.variable_scope(name), scope => | |||||
| { | |||||
| input_data = convolutional(input_data, filters_shape: new int[] { 1, 1, input_channel, filter_num1 }, | |||||
| trainable: trainable, name: "conv1"); | |||||
| input_data = convolutional(input_data, filters_shape: new int[] { 3, 3, filter_num1, filter_num2 }, | |||||
| trainable: trainable, name: "conv2"); | |||||
| var residual_output = input_data + short_cut; | |||||
| return residual_output; | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,94 +0,0 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Text; | |||||
| namespace TensorFlowNET.Examples.ImageProcessing.YOLO | |||||
| { | |||||
| public class Config | |||||
| { | |||||
| public YoloConfig YOLO; | |||||
| public TrainConfig TRAIN; | |||||
| public TestConfig TEST; | |||||
| public Config(string root) | |||||
| { | |||||
| YOLO = new YoloConfig(root); | |||||
| TRAIN = new TrainConfig(root); | |||||
| TEST = new TestConfig(root); | |||||
| } | |||||
| public class YoloConfig | |||||
| { | |||||
| string _root; | |||||
| public string CLASSES; | |||||
| public string ANCHORS; | |||||
| public float MOVING_AVE_DECAY = 0.9995f; | |||||
| public int[] STRIDES = new int[] { 8, 16, 32 }; | |||||
| public int ANCHOR_PER_SCALE = 3; | |||||
| public float IOU_LOSS_THRESH = 0.5f; | |||||
| public string UPSAMPLE_METHOD = "resize"; | |||||
| public string ORIGINAL_WEIGHT; | |||||
| public string DEMO_WEIGHT; | |||||
| public YoloConfig(string root) | |||||
| { | |||||
| _root = root; | |||||
| CLASSES = Path.Combine(_root, "data", "classes", "coco.names"); | |||||
| ANCHORS = Path.Combine(_root, "data", "anchors", "basline_anchors.txt"); | |||||
| ORIGINAL_WEIGHT = Path.Combine(_root, "checkpoint", "yolov3_coco.ckpt"); | |||||
| DEMO_WEIGHT = Path.Combine(_root, "checkpoint", "yolov3_coco_demo.ckpt"); | |||||
| } | |||||
| } | |||||
| public class TrainConfig | |||||
| { | |||||
| string _root; | |||||
| public int BATCH_SIZE = 6; | |||||
| public int[] INPUT_SIZE = new int[] { 320, 352, 384, 416, 448, 480, 512, 544, 576, 608 }; | |||||
| public bool DATA_AUG = true; | |||||
| public float LEARN_RATE_INIT = 1e-4f; | |||||
| public float LEARN_RATE_END = 1e-6f; | |||||
| public int WARMUP_EPOCHS = 2; | |||||
| public int FISRT_STAGE_EPOCHS = 20; | |||||
| public int SECOND_STAGE_EPOCHS = 30; | |||||
| public string INITIAL_WEIGHT; | |||||
| public string ANNOT_PATH; | |||||
| public TrainConfig(string root) | |||||
| { | |||||
| _root = root; | |||||
| INITIAL_WEIGHT = Path.Combine(_root, "checkpoint", "yolov3_coco_demo.ckpt"); | |||||
| ANNOT_PATH = Path.Combine(_root, "data", "dataset", "voc_train.txt"); | |||||
| } | |||||
| } | |||||
| public class TestConfig | |||||
| { | |||||
| string _root; | |||||
| public int BATCH_SIZE = 2; | |||||
| public int[] INPUT_SIZE = new int[] { 544 }; | |||||
| public bool DATA_AUG = false; | |||||
| public bool WRITE_IMAGE = true; | |||||
| public string WRITE_IMAGE_PATH; | |||||
| public string WEIGHT_FILE; | |||||
| public bool WRITE_IMAGE_SHOW_LABEL = true; | |||||
| public bool SHOW_LABEL = true; | |||||
| public int SECOND_STAGE_EPOCHS = 30; | |||||
| public float SCORE_THRESHOLD = 0.3f; | |||||
| public float IOU_THRESHOLD = 0.45f; | |||||
| public string ANNOT_PATH; | |||||
| public TestConfig(string root) | |||||
| { | |||||
| _root = root; | |||||
| ANNOT_PATH = Path.Combine(_root, "data", "dataset", "voc_test.txt"); | |||||
| WRITE_IMAGE_PATH = Path.Combine(_root, "data", "detection"); | |||||
| WEIGHT_FILE = Path.Combine(_root, "checkpoint", "yolov3_test_loss=9.2099.ckpt-5"); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,99 +0,0 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using Tensorflow; | |||||
| using Keras.Layers; | |||||
| using NumSharp; | |||||
| using Keras; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| public class Keras : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public string Name => "Keras"; | |||||
| public bool Run() | |||||
| { | |||||
| Console.WriteLine("================================== Keras =================================="); | |||||
| #region data | |||||
| var batch_size = 1000; | |||||
| var (X, Y) = XOR(batch_size); | |||||
| //var (X, Y, batch_size) = (np.array(new float[,]{{1, 0 },{1, 1 },{0, 0 },{0, 1 }}), np.array(new int[] { 0, 1, 1, 0 }), 4); | |||||
| #endregion | |||||
| #region features | |||||
| var (features, labels) = (new Tensor(X), new Tensor(Y)); | |||||
| var num_steps = 10000; | |||||
| #endregion | |||||
| #region model | |||||
| var m = new Model(); | |||||
| //m.Add(new Dense(8, name: "Hidden", activation: tf.nn.relu())).Add(new Dense(1, name:"Output")); | |||||
| m.Add( | |||||
| new ILayer[] { | |||||
| new Dense(8, name: "Hidden_1", activation: tf.nn.relu()), | |||||
| new Dense(1, name: "Output") | |||||
| }); | |||||
| m.train(num_steps, (X, Y)); | |||||
| #endregion | |||||
| return true; | |||||
| } | |||||
| static (NDArray, NDArray) XOR(int samples) | |||||
| { | |||||
| var X = new List<float[]>(); | |||||
| var Y = new List<float>(); | |||||
| var r = new Random(); | |||||
| for (int i = 0; i < samples; i++) | |||||
| { | |||||
| var x1 = (float)r.Next(0, 2); | |||||
| var x2 = (float)r.Next(0, 2); | |||||
| var y = 0.0f; | |||||
| if (x1 == x2) | |||||
| y = 1.0f; | |||||
| X.Add(new float[] { x1, x2 }); | |||||
| Y.Add(y); | |||||
| } | |||||
| return (np.array(X.ToArray()), np.array(Y.ToArray())); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,153 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Diagnostics; | |||||
| using System.Text; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// How to optimise your input pipeline with queues and multi-threading | |||||
| /// https://blog.metaflow.fr/tensorflow-how-to-optimise-your-input-pipeline-with-queues-and-multi-threading-e7c3874157e0 | |||||
| /// </summary> | |||||
| public class FullyConnected : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public bool IsImportingGraph { get; set; } | |||||
| public string Name => "Fully Connected Neural Network"; | |||||
| Tensor input = null; | |||||
| Tensor x_inputs_data = null; | |||||
| Tensor y_inputs_data = null; | |||||
| Tensor accuracy = null; | |||||
| Tensor y_true = null; | |||||
| Tensor loss_op = null; | |||||
| Operation train_op = null; | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| var g = tf.get_default_graph(); | |||||
| Tensor z = null; | |||||
| tf_with(tf.variable_scope("placeholder"), delegate | |||||
| { | |||||
| input = tf.placeholder(tf.float32, shape: (-1, 1024)); | |||||
| y_true = tf.placeholder(tf.int32, shape: (-1, 1)); | |||||
| }); | |||||
| tf_with(tf.variable_scope("FullyConnected"), delegate | |||||
| { | |||||
| var w = tf.get_variable("w", shape: (1024, 1024), initializer: tf.random_normal_initializer(stddev: 0.1f)); | |||||
| var b = tf.get_variable("b", shape: 1024, initializer: tf.constant_initializer(0.1)); | |||||
| z = tf.matmul(input, w) + b; | |||||
| var y = tf.nn.relu(z); | |||||
| var w2 = tf.get_variable("w2", shape: (1024, 1), initializer: tf.random_normal_initializer(stddev: 0.1f)); | |||||
| var b2 = tf.get_variable("b2", shape: 1, initializer: tf.constant_initializer(0.1)); | |||||
| z = tf.matmul(y, w2) + b2; | |||||
| }); | |||||
| tf_with(tf.variable_scope("Loss"), delegate | |||||
| { | |||||
| var losses = tf.nn.sigmoid_cross_entropy_with_logits(tf.cast(y_true, tf.float32), z); | |||||
| loss_op = tf.reduce_mean(losses); | |||||
| }); | |||||
| tf_with(tf.variable_scope("Accuracy"), delegate | |||||
| { | |||||
| var y_pred = tf.cast(z > 0, tf.int32); | |||||
| accuracy = tf.reduce_mean(tf.cast(tf.equal(y_pred, y_true), tf.float32)); | |||||
| // accuracy = tf.Print(accuracy, data =[accuracy], message = "accuracy:") | |||||
| }); | |||||
| // We add the training operation, ... | |||||
| var adam = tf.train.AdamOptimizer(0.01f); | |||||
| train_op = adam.minimize(loss_op, name: "train_op"); | |||||
| return g; | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| // batches of 128 samples, each containing 1024 data points | |||||
| x_inputs_data = tf.random_normal(new[] { 128, 1024 }, mean: 0, stddev: 1); | |||||
| // We will try to predict this law: | |||||
| // predict 1 if the sum of the elements is positive and 0 otherwise | |||||
| y_inputs_data = tf.cast(tf.reduce_sum(x_inputs_data, axis: 1, keepdims: true) > 0, tf.int32); | |||||
| } | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| var g = BuildGraph(); | |||||
| using (var sess = tf.Session()) | |||||
| Train(sess); | |||||
| return true; | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| var sw = new Stopwatch(); | |||||
| sw.Start(); | |||||
| // init variables | |||||
| sess.run(tf.global_variables_initializer()); | |||||
| // check the accuracy before training | |||||
| var (x_input, y_input) = sess.run((x_inputs_data, y_inputs_data)); | |||||
| sess.run(accuracy, (input, x_input), (y_true, y_input)); | |||||
| // training | |||||
| foreach (var i in range(5000)) | |||||
| { | |||||
| // by sampling some input data (fetching) | |||||
| (x_input, y_input) = sess.run((x_inputs_data, y_inputs_data)); | |||||
| var (_, loss) = sess.run((train_op, loss_op), (input, x_input), (y_true, y_input)); | |||||
| // We regularly check the loss | |||||
| if (i % 500 == 0) | |||||
| print($"iter:{i} - loss:{loss}"); | |||||
| } | |||||
| // Finally, we check our final accuracy | |||||
| (x_input, y_input) = sess.run((x_inputs_data, y_inputs_data)); | |||||
| sess.run(accuracy, (input, x_input), (y_true, y_input)); | |||||
| print($"Time taken: {sw.Elapsed.TotalSeconds}s"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,129 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Diagnostics; | |||||
| using System.Text; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// How to optimise your input pipeline with queues and multi-threading | |||||
| /// https://blog.metaflow.fr/tensorflow-how-to-optimise-your-input-pipeline-with-queues-and-multi-threading-e7c3874157e0 | |||||
| /// </summary> | |||||
| public class FullyConnectedInQueue : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = false; | |||||
| public bool IsImportingGraph { get; set; } | |||||
| public string Name => "Fully Connected Neural Network In Queue"; | |||||
| Tensor input = null; | |||||
| Tensor x_inputs_data = null; | |||||
| Tensor y_inputs_data = null; | |||||
| Tensor accuracy = null; | |||||
| Tensor y_true = null; | |||||
| Tensor loss_op = null; | |||||
| Operation train_op = null; | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| var g = tf.get_default_graph(); | |||||
| Tensor z = null; | |||||
| // We build our small model: a basic two layers neural net with ReLU | |||||
| tf_with(tf.variable_scope("queue"), delegate | |||||
| { | |||||
| // enqueue 5 batches | |||||
| var q = tf.FIFOQueue(capacity: 5, dtype: tf.float32); | |||||
| // We use the "enqueue" operation so 1 element of the queue is the full batch | |||||
| var enqueue_op = q.enqueue(x_inputs_data); | |||||
| var numberOfThreads = 1; | |||||
| // var qr = tf.train.QueueRunner(q, [enqueue_op] * numberOfThreads); | |||||
| }); | |||||
| return g; | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| // batches of 128 samples, each containing 1024 data points | |||||
| x_inputs_data = tf.random_normal(new[] { 128, 1024 }, mean: 0, stddev: 1); | |||||
| // We will try to predict this law: | |||||
| // predict 1 if the sum of the elements is positive and 0 otherwise | |||||
| y_inputs_data = tf.cast(tf.reduce_sum(x_inputs_data, axis: 1, keepdims: true) > 0, tf.int32); | |||||
| } | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| var g = BuildGraph(); | |||||
| using (var sess = tf.Session()) | |||||
| Train(sess); | |||||
| return true; | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| var sw = new Stopwatch(); | |||||
| sw.Start(); | |||||
| // init variables | |||||
| sess.run(tf.global_variables_initializer()); | |||||
| // check the accuracy before training | |||||
| var (x_input, y_input) = sess.run((x_inputs_data, y_inputs_data)); | |||||
| sess.run(accuracy, (input, x_input), (y_true, y_input)); | |||||
| // training | |||||
| foreach (var i in range(5000)) | |||||
| { | |||||
| // by sampling some input data (fetching) | |||||
| (x_input, y_input) = sess.run((x_inputs_data, y_inputs_data)); | |||||
| var (_, loss) = sess.run((train_op, loss_op), (input, x_input), (y_true, y_input)); | |||||
| // We regularly check the loss | |||||
| if (i % 500 == 0) | |||||
| print($"iter:{i} - loss:{loss}"); | |||||
| } | |||||
| // Finally, we check our final accuracy | |||||
| (x_input, y_input) = sess.run((x_inputs_data, y_inputs_data)); | |||||
| sess.run(accuracy, (input, x_input), (y_true, y_input)); | |||||
| print($"Time taken: {sw.Elapsed.TotalSeconds}s"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,190 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using System; | |||||
| using NumSharp; | |||||
| using Tensorflow; | |||||
| using TensorFlowNET.Examples.Utility; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Simple vanilla neural net solving the famous XOR problem | |||||
| /// https://github.com/amygdala/tensorflow-workshop/blob/master/workshop_sections/getting_started/xor/README.md | |||||
| /// </summary> | |||||
| public class NeuralNetXor : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public string Name => "NN XOR"; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public int num_steps = 10000; | |||||
| private NDArray data; | |||||
| private (Operation, Tensor, Tensor) make_graph(Tensor features,Tensor labels, int num_hidden = 8) | |||||
| { | |||||
| var stddev = 1 / Math.Sqrt(2); | |||||
| var hidden_weights = tf.Variable(tf.truncated_normal(new int []{2, num_hidden}, seed:1, stddev: (float) stddev )); | |||||
| // Shape [4, num_hidden] | |||||
| var hidden_activations = tf.nn.relu(tf.matmul(features, hidden_weights)); | |||||
| var output_weights = tf.Variable(tf.truncated_normal( | |||||
| new[] {num_hidden, 1}, | |||||
| seed: 17, | |||||
| stddev: (float) (1 / Math.Sqrt(num_hidden)) | |||||
| )); | |||||
| // Shape [4, 1] | |||||
| var logits = tf.matmul(hidden_activations, output_weights); | |||||
| // Shape [4] | |||||
| var predictions = tf.tanh(tf.squeeze(logits)); | |||||
| var loss = tf.reduce_mean(tf.square(predictions - tf.cast(labels, tf.float32)), name:"loss"); | |||||
| var gs = tf.Variable(0, trainable: false, name: "global_step"); | |||||
| var train_op = tf.train.GradientDescentOptimizer(0.2f).minimize(loss, global_step: gs); | |||||
| return (train_op, loss, gs); | |||||
| } | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| float loss_value = 0; | |||||
| if (IsImportingGraph) | |||||
| loss_value = RunWithImportedGraph(); | |||||
| else | |||||
| loss_value = RunWithBuiltGraph(); | |||||
| return loss_value < 0.0628; | |||||
| } | |||||
| private float RunWithImportedGraph() | |||||
| { | |||||
| var graph = tf.Graph().as_default(); | |||||
| tf.train.import_meta_graph("graph/xor.meta"); | |||||
| Tensor features = graph.get_operation_by_name("Placeholder"); | |||||
| Tensor labels = graph.get_operation_by_name("Placeholder_1"); | |||||
| Tensor loss = graph.get_operation_by_name("loss"); | |||||
| Tensor train_op = graph.get_operation_by_name("train_op"); | |||||
| Tensor global_step = graph.get_operation_by_name("global_step"); | |||||
| var init = tf.global_variables_initializer(); | |||||
| float loss_value = 0; | |||||
| // Start tf session | |||||
| using (var sess = tf.Session(graph)) | |||||
| { | |||||
| sess.run(init); | |||||
| var step = 0; | |||||
| var y_ = np.array(new int[] { 1, 0, 0, 1 }, dtype: np.int32); | |||||
| while (step < num_steps) | |||||
| { | |||||
| // original python: | |||||
| //_, step, loss_value = sess.run( | |||||
| // [train_op, gs, loss], | |||||
| // feed_dict={features: xy, labels: y_} | |||||
| // ) | |||||
| (_, step, loss_value) = sess.run((train_op, global_step, loss), (features, data), (labels, y_)); | |||||
| if (step == 1 || step % 1000 == 0) | |||||
| Console.WriteLine($"Step {step} loss: {loss_value}"); | |||||
| } | |||||
| Console.WriteLine($"Final loss: {loss_value}"); | |||||
| } | |||||
| return loss_value; | |||||
| } | |||||
| private float RunWithBuiltGraph() | |||||
| { | |||||
| var graph = tf.Graph().as_default(); | |||||
| var features = tf.placeholder(tf.float32, new TensorShape(4, 2)); | |||||
| var labels = tf.placeholder(tf.int32, new TensorShape(4)); | |||||
| var (train_op, loss, gs) = make_graph(features, labels); | |||||
| var init = tf.global_variables_initializer(); | |||||
| float loss_value = 0; | |||||
| // Start tf session | |||||
| using (var sess = tf.Session(graph)) | |||||
| { | |||||
| sess.run(init); | |||||
| var step = 0; | |||||
| var y_ = np.array(new int[] { 1, 0, 0, 1 }, dtype: np.int32); | |||||
| while (step < num_steps) | |||||
| { | |||||
| (_, step, loss_value) = sess.run((train_op, gs, loss), (features, data), (labels, y_)); | |||||
| if (step == 1 || step % 1000 == 0) | |||||
| Console.WriteLine($"Step {step} loss: {loss_value}"); | |||||
| } | |||||
| Console.WriteLine($"Final loss: {loss_value}"); | |||||
| } | |||||
| return loss_value; | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| data = new float[,] | |||||
| { | |||||
| {1, 0 }, | |||||
| {1, 1 }, | |||||
| {0, 0 }, | |||||
| {0, 1 } | |||||
| }; | |||||
| if (IsImportingGraph) | |||||
| { | |||||
| // download graph meta data | |||||
| string url = "https://raw.githubusercontent.com/SciSharp/TensorFlow.NET/master/graph/xor.meta"; | |||||
| Web.Download(url, "graph", "xor.meta"); | |||||
| } | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,120 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Diagnostics; | |||||
| using System.Drawing; | |||||
| using System.Linq; | |||||
| using System.Reflection; | |||||
| using Tensorflow; | |||||
| using Console = Colorful.Console; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| class Program | |||||
| { | |||||
| static void Main(string[] args) | |||||
| { | |||||
| int finished = 0; | |||||
| var errors = new List<string>(); | |||||
| var success = new List<string>(); | |||||
| var parsedArgs = ParseArgs(args); | |||||
| var examples = Assembly.GetEntryAssembly().GetTypes() | |||||
| .Where(x => x.GetInterfaces().Contains(typeof(IExample))) | |||||
| .Select(x => (IExample)Activator.CreateInstance(x)) | |||||
| .Where(x => x.Enabled) | |||||
| .OrderBy(x => x.Name) | |||||
| .ToArray(); | |||||
| if (parsedArgs.ContainsKey("ex")) | |||||
| examples = examples.Where(x => x.Name == parsedArgs["ex"]).ToArray(); | |||||
| Console.WriteLine(Environment.OSVersion.ToString(), Color.Yellow); | |||||
| Console.WriteLine($"TensorFlow Binary v{tf.VERSION}", Color.Yellow); | |||||
| Console.WriteLine($"TensorFlow.NET v{Assembly.GetAssembly(typeof(TF_DataType)).GetName().Version}", Color.Yellow); | |||||
| for (var i = 0; i < examples.Length; i++) | |||||
| Console.WriteLine($"[{i}]: {examples[i].Name}"); | |||||
| var key = "0"; | |||||
| if (examples.Length > 1) | |||||
| { | |||||
| Console.Write($"Choose one example to run, hit [Enter] to run all: ", Color.Yellow); | |||||
| key = Console.ReadLine(); | |||||
| } | |||||
| var sw = new Stopwatch(); | |||||
| for (var i = 0; i < examples.Length; i++) | |||||
| { | |||||
| if (i.ToString() != key && key != "") continue; | |||||
| var example = examples[i]; | |||||
| Console.WriteLine($"{DateTime.UtcNow} Starting {example.Name}", Color.White); | |||||
| try | |||||
| { | |||||
| sw.Restart(); | |||||
| bool isSuccess = example.Run(); | |||||
| sw.Stop(); | |||||
| if (isSuccess) | |||||
| success.Add($"Example: {example.Name} in {sw.Elapsed.TotalSeconds}s"); | |||||
| else | |||||
| errors.Add($"Example: {example.Name} in {sw.Elapsed.TotalSeconds}s"); | |||||
| } | |||||
| catch (Exception ex) | |||||
| { | |||||
| errors.Add($"Example: {example.Name}"); | |||||
| Console.WriteLine(ex); | |||||
| } | |||||
| finished++; | |||||
| Console.WriteLine($"{DateTime.UtcNow} Completed {example.Name}", Color.White); | |||||
| } | |||||
| success.ForEach(x => Console.WriteLine($"{x} is OK!", Color.Green)); | |||||
| errors.ForEach(x => Console.WriteLine($"{x} is Failed!", Color.Red)); | |||||
| Console.WriteLine($"{finished} of {examples.Length} example(s) are completed."); | |||||
| Console.ReadLine(); | |||||
| } | |||||
| private static Dictionary<string, string> ParseArgs(string[] args) | |||||
| { | |||||
| var parsed = new Dictionary<string, string>(); | |||||
| for (int i = 0; i < args.Length; i++) | |||||
| { | |||||
| string key = args[i].Substring(1); | |||||
| switch (key) | |||||
| { | |||||
| case "ex": | |||||
| parsed.Add(key, args[++i]); | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| } | |||||
| return parsed; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,32 +0,0 @@ | |||||
| <Project Sdk="Microsoft.NET.Sdk"> | |||||
| <PropertyGroup> | |||||
| <OutputType>Exe</OutputType> | |||||
| <TargetFramework>netcoreapp3.0</TargetFramework> | |||||
| <GeneratePackageOnBuild>false</GeneratePackageOnBuild> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | |||||
| <DefineConstants>DEBUG;TRACE</DefineConstants> | |||||
| </PropertyGroup> | |||||
| <ItemGroup> | |||||
| <Compile Remove="Keras.cs" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <PackageReference Include="Colorful.Console" Version="1.2.9" /> | |||||
| <PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> | |||||
| <PackageReference Include="SciSharp.TensorFlow.Redist" Version="1.14.0" /> | |||||
| <PackageReference Include="SharpZipLib" Version="1.1.0" /> | |||||
| <PackageReference Include="System.Drawing.Common" Version="4.5.1" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <ProjectReference Include="..\..\src\TensorFlowDatasets\TensorFlowDatasets.csproj" /> | |||||
| <ProjectReference Include="..\..\src\TensorFlowNET.Core\TensorFlowNET.Core.csproj" /> | |||||
| <ProjectReference Include="..\..\src\TensorFlowNET.Models\TensorFlowNET.Models.csproj" /> | |||||
| <ProjectReference Include="..\..\src\TensorFlowText\TensorFlowText.csproj" /> | |||||
| <ProjectReference Include="..\..\src\TensorFlowHub\TensorFlowHub.csproj" /> | |||||
| </ItemGroup> | |||||
| </Project> | |||||
| @@ -1,164 +0,0 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using Tensorflow; | |||||
| using Newtonsoft.Json; | |||||
| using System.Linq; | |||||
| using NumSharp; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// This example classifies movie reviews as positive or negative using the text of the review. | |||||
| /// This is a binary—or two-class—classification, an important and widely applicable kind of machine learning problem. | |||||
| /// https://github.com/tensorflow/docs/blob/master/site/en/tutorials/keras/basic_text_classification.ipynb | |||||
| /// </summary> | |||||
| public class BinaryTextClassification : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = false; | |||||
| public string Name => "Binary Text Classification"; | |||||
| public bool IsImportingGraph { get; set; } = true; | |||||
| string dir = "binary_text_classification"; | |||||
| string dataFile = "imdb.zip"; | |||||
| NDArray train_data, train_labels, test_data, test_labels; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| Console.WriteLine($"Training entries: {train_data.shape[0]}, labels: {train_labels.shape[0]}"); | |||||
| // A dictionary mapping words to an integer index | |||||
| var word_index = GetWordIndex(); | |||||
| /*train_data = keras.preprocessing.sequence.pad_sequences(train_data, | |||||
| value: word_index["<PAD>"], | |||||
| padding: "post", | |||||
| maxlen: 256); | |||||
| test_data = keras.preprocessing.sequence.pad_sequences(test_data, | |||||
| value: word_index["<PAD>"], | |||||
| padding: "post", | |||||
| maxlen: 256);*/ | |||||
| // input shape is the vocabulary count used for the movie reviews (10,000 words) | |||||
| int vocab_size = 10000; | |||||
| var model = keras.Sequential(); | |||||
| var layer = keras.layers.Embedding(vocab_size, 16); | |||||
| model.add(layer); | |||||
| return false; | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| Directory.CreateDirectory(dir); | |||||
| // get model file | |||||
| string url = $"https://github.com/SciSharp/TensorFlow.NET/raw/master/data/{dataFile}"; | |||||
| Utility.Web.Download(url, dir, "imdb.zip"); | |||||
| Utility.Compress.UnZip(Path.Join(dir, $"imdb.zip"), dir); | |||||
| // prepare training dataset | |||||
| var x_train = ReadData(Path.Join(dir, "x_train.txt")); | |||||
| var labels_train = ReadData(Path.Join(dir, "y_train.txt")); | |||||
| var indices_train = ReadData(Path.Join(dir, "indices_train.txt")); | |||||
| x_train = x_train[indices_train]; | |||||
| labels_train = labels_train[indices_train]; | |||||
| var x_test = ReadData(Path.Join(dir, "x_test.txt")); | |||||
| var labels_test = ReadData(Path.Join(dir, "y_test.txt")); | |||||
| var indices_test = ReadData(Path.Join(dir, "indices_test.txt")); | |||||
| x_test = x_test[indices_test]; | |||||
| labels_test = labels_test[indices_test]; | |||||
| // not completed | |||||
| var xs = x_train.hstack(x_test); | |||||
| var labels = labels_train.hstack(labels_test); | |||||
| var idx = x_train.size; | |||||
| var y_train = labels_train; | |||||
| var y_test = labels_test; | |||||
| // convert x_train | |||||
| train_data = new NDArray(np.int32, (x_train.size, 256)); | |||||
| /*for (int i = 0; i < x_train.size; i++) | |||||
| train_data[i] = x_train[i].Data<string>()[1].Split(',').Select(x => int.Parse(x)).ToArray();*/ | |||||
| test_data = new NDArray(np.int32, (x_test.size, 256)); | |||||
| /*for (int i = 0; i < x_test.size; i++) | |||||
| test_data[i] = x_test[i].Data<string>()[1].Split(',').Select(x => int.Parse(x)).ToArray();*/ | |||||
| train_labels = y_train; | |||||
| test_labels = y_test; | |||||
| } | |||||
| private NDArray ReadData(string file) | |||||
| { | |||||
| var lines = File.ReadAllLines(file); | |||||
| var nd = new NDArray(lines[0].StartsWith("[") ? typeof(string) : np.int32, new Shape(lines.Length)); | |||||
| if (lines[0].StartsWith("[")) | |||||
| { | |||||
| for (int i = 0; i < lines.Length; i++) | |||||
| { | |||||
| /*var matches = Regex.Matches(lines[i], @"\d+\s*"); | |||||
| var data = new int[matches.Count]; | |||||
| for (int j = 0; j < data.Length; j++) | |||||
| data[j] = Convert.ToInt32(matches[j].Value); | |||||
| nd[i] = data.ToArray();*/ | |||||
| nd[i] = lines[i].Substring(1, lines[i].Length - 2).Replace(" ", string.Empty); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| for (int i = 0; i < lines.Length; i++) | |||||
| nd[i] = Convert.ToInt32(lines[i]); | |||||
| } | |||||
| return nd; | |||||
| } | |||||
| private Dictionary<string, int> GetWordIndex() | |||||
| { | |||||
| var result = new Dictionary<string, int>(); | |||||
| var json = File.ReadAllText(Path.Join(dir, "imdb_word_index.json")); | |||||
| var dict = JsonConvert.DeserializeObject<Dictionary<string, int>>(json); | |||||
| dict.Keys.Select(k => result[k] = dict[k] + 3).ToList(); | |||||
| result["<PAD>"] = 0; | |||||
| result["<START>"] = 1; | |||||
| result["<UNK>"] = 2; // unknown | |||||
| result["<UNUSED>"] = 3; | |||||
| return result; | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,272 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Diagnostics; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using NumSharp; | |||||
| using Tensorflow; | |||||
| using Tensorflow.Sessions; | |||||
| using TensorFlowNET.Examples.Text; | |||||
| using TensorFlowNET.Examples.Utility; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// https://github.com/dongjun-Lee/text-classification-models-tf | |||||
| /// </summary> | |||||
| public class CnnTextClassification : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public string Name => "CNN Text Classification"; | |||||
| public int? DataLimit = null; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| const string dataDir = "cnn_text"; | |||||
| string dataFileName = "dbpedia_csv.tar.gz"; | |||||
| string TRAIN_PATH = $"{dataDir}/dbpedia_csv/train.csv"; | |||||
| string TEST_PATH = $"{dataDir}/dbpedia_csv/test.csv"; | |||||
| int NUM_CLASS = 14; | |||||
| int BATCH_SIZE = 64; | |||||
| int NUM_EPOCHS = 10; | |||||
| int WORD_MAX_LEN = 100; | |||||
| int CHAR_MAX_LEN = 1014; | |||||
| float loss_value = 0; | |||||
| double max_accuracy = 0; | |||||
| int alphabet_size = -1; | |||||
| int vocabulary_size = -1; | |||||
| NDArray train_x, valid_x, train_y, valid_y; | |||||
| ITextModel textModel; | |||||
| public string ModelName = "word_cnn"; // word_cnn | char_cnn | vd_cnn | word_rnn | att_rnn | rcnn | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| var graph = IsImportingGraph ? ImportGraph() : BuildGraph(); | |||||
| using (var sess = tf.Session(graph)) | |||||
| Train(sess); | |||||
| return max_accuracy > 0.9; | |||||
| } | |||||
| // TODO: this originally is an SKLearn utility function. it randomizes train and test which we don't do here | |||||
| private (NDArray, NDArray, NDArray, NDArray) train_test_split(NDArray x, NDArray y, float test_size = 0.3f) | |||||
| { | |||||
| Console.WriteLine("Splitting in Training and Testing data..."); | |||||
| int len = x.shape[0]; | |||||
| //int classes = y.Data<int>().Distinct().Count(); | |||||
| //int samples = len / classes; | |||||
| int train_size = (int)Math.Round(len * (1 - test_size)); | |||||
| train_x = x[new Slice(stop: train_size), new Slice()]; | |||||
| valid_x = x[new Slice(start: train_size), new Slice()]; | |||||
| train_y = y[new Slice(stop: train_size)]; | |||||
| valid_y = y[new Slice(start: train_size)]; | |||||
| Console.WriteLine("\tDONE"); | |||||
| return (train_x, valid_x, train_y, valid_y); | |||||
| } | |||||
| private void FillWithShuffledLabels(int[][] x, int[] y, int[][] shuffled_x, int[] shuffled_y, Random random, Dictionary<int, HashSet<int>> labels) | |||||
| { | |||||
| int i = 0; | |||||
| var label_keys = labels.Keys.ToArray(); | |||||
| while (i < shuffled_x.Length) | |||||
| { | |||||
| var key = label_keys[random.Next(label_keys.Length)]; | |||||
| var set = labels[key]; | |||||
| var index = set.First(); | |||||
| if (set.Count == 0) | |||||
| { | |||||
| labels.Remove(key); // remove the set as it is empty | |||||
| label_keys = labels.Keys.ToArray(); | |||||
| } | |||||
| shuffled_x[i] = x[index]; | |||||
| shuffled_y[i] = y[index]; | |||||
| i++; | |||||
| } | |||||
| } | |||||
| private IEnumerable<(NDArray, NDArray, int)> batch_iter(NDArray inputs, NDArray outputs, int batch_size, int num_epochs) | |||||
| { | |||||
| var num_batches_per_epoch = (len(inputs) - 1) / batch_size + 1; | |||||
| var total_batches = num_batches_per_epoch * num_epochs; | |||||
| foreach (var epoch in range(num_epochs)) | |||||
| { | |||||
| foreach (var batch_num in range(num_batches_per_epoch)) | |||||
| { | |||||
| var start_index = batch_num * batch_size; | |||||
| var end_index = Math.Min((batch_num + 1) * batch_size, len(inputs)); | |||||
| if (end_index <= start_index) | |||||
| break; | |||||
| yield return (inputs[new Slice(start_index, end_index)], outputs[new Slice(start_index, end_index)], total_batches); | |||||
| } | |||||
| } | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| // full dataset https://github.com/le-scientifique/torchDatasets/raw/master/dbpedia_csv.tar.gz | |||||
| var url = "https://raw.githubusercontent.com/SciSharp/TensorFlow.NET/master/data/dbpedia_subset.zip"; | |||||
| Web.Download(url, dataDir, "dbpedia_subset.zip"); | |||||
| Compress.UnZip(Path.Combine(dataDir, "dbpedia_subset.zip"), Path.Combine(dataDir, "dbpedia_csv")); | |||||
| Console.WriteLine("Building dataset..."); | |||||
| var (x, y) = (new int[0][], new int[0]); | |||||
| if(ModelName == "char_cnn") | |||||
| { | |||||
| (x, y, alphabet_size) = DataHelpers.build_char_dataset(TRAIN_PATH, "char_cnn", CHAR_MAX_LEN); | |||||
| } | |||||
| else | |||||
| { | |||||
| var word_dict = DataHelpers.build_word_dict(TRAIN_PATH); | |||||
| vocabulary_size = len(word_dict); | |||||
| (x, y) = DataHelpers.build_word_dataset(TRAIN_PATH, word_dict, WORD_MAX_LEN); | |||||
| } | |||||
| Console.WriteLine("\tDONE "); | |||||
| var (train_x, valid_x, train_y, valid_y) = train_test_split(x, y, test_size: 0.15f); | |||||
| Console.WriteLine("Training set size: " + train_x.shape[0]); | |||||
| Console.WriteLine("Test set size: " + valid_x.shape[0]); | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| var graph = tf.Graph().as_default(); | |||||
| // download graph meta data | |||||
| var meta_file = "word_cnn.meta"; | |||||
| var meta_path = Path.Combine("graph", meta_file); | |||||
| if (File.GetLastWriteTime(meta_path) < new DateTime(2019, 05, 11)) | |||||
| { | |||||
| // delete old cached file which contains errors | |||||
| Console.WriteLine("Discarding cached file: " + meta_path); | |||||
| if(File.Exists(meta_path)) | |||||
| File.Delete(meta_path); | |||||
| } | |||||
| var url = "https://raw.githubusercontent.com/SciSharp/TensorFlow.NET/master/graph/" + meta_file; | |||||
| Web.Download(url, "graph", meta_file); | |||||
| Console.WriteLine("Import graph..."); | |||||
| tf.train.import_meta_graph(Path.Join("graph", meta_file)); | |||||
| Console.WriteLine("\tDONE "); | |||||
| return graph; | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| var graph = tf.Graph().as_default(); | |||||
| switch (ModelName) | |||||
| { | |||||
| case "word_cnn": | |||||
| textModel = new WordCnn(vocabulary_size, WORD_MAX_LEN, NUM_CLASS); | |||||
| break; | |||||
| case "char_cnn": | |||||
| textModel = new CharCnn(alphabet_size, CHAR_MAX_LEN, NUM_CLASS); | |||||
| break; | |||||
| } | |||||
| return graph; | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| var graph = tf.get_default_graph(); | |||||
| sess.run(tf.global_variables_initializer()); | |||||
| var saver = tf.train.Saver(tf.global_variables()); | |||||
| var train_batches = batch_iter(train_x, train_y, BATCH_SIZE, NUM_EPOCHS); | |||||
| var num_batches_per_epoch = (len(train_x) - 1) / BATCH_SIZE + 1; | |||||
| Tensor is_training = graph.OperationByName("is_training"); | |||||
| Tensor model_x = graph.OperationByName("x"); | |||||
| Tensor model_y = graph.OperationByName("y"); | |||||
| Tensor loss = graph.OperationByName("loss/Mean"); | |||||
| Operation optimizer = graph.OperationByName("loss/Adam"); | |||||
| Tensor global_step = graph.OperationByName("Variable"); | |||||
| Tensor accuracy = graph.OperationByName("accuracy/accuracy"); | |||||
| var sw = new Stopwatch(); | |||||
| sw.Start(); | |||||
| int step = 0; | |||||
| foreach (var (x_batch, y_batch, total) in train_batches) | |||||
| { | |||||
| (_, step, loss_value) = sess.run((optimizer, global_step, loss), | |||||
| (model_x, x_batch), (model_y, y_batch), (is_training, true)); | |||||
| if (step % 10 == 0) | |||||
| { | |||||
| Console.WriteLine($"Training on batch {step}/{total} loss: {loss_value.ToString("0.0000")} {sw.ElapsedMilliseconds}ms."); | |||||
| sw.Restart(); | |||||
| } | |||||
| if (step % 100 == 0) | |||||
| { | |||||
| // Test accuracy with validation data for each epoch. | |||||
| var valid_batches = batch_iter(valid_x, valid_y, BATCH_SIZE, 1); | |||||
| var (sum_accuracy, cnt) = (0.0f, 0); | |||||
| foreach (var (valid_x_batch, valid_y_batch, total_validation_batches) in valid_batches) | |||||
| { | |||||
| var valid_feed_dict = new FeedDict | |||||
| { | |||||
| [model_x] = valid_x_batch, | |||||
| [model_y] = valid_y_batch, | |||||
| [is_training] = false | |||||
| }; | |||||
| float accuracy_value = sess.run(accuracy, (model_x, valid_x_batch), (model_y, valid_y_batch), (is_training, false)); | |||||
| sum_accuracy += accuracy_value; | |||||
| cnt += 1; | |||||
| } | |||||
| var valid_accuracy = sum_accuracy / cnt; | |||||
| print($"\nValidation Accuracy = {valid_accuracy.ToString("P")}\n"); | |||||
| // Save model | |||||
| if (valid_accuracy > max_accuracy) | |||||
| { | |||||
| max_accuracy = valid_accuracy; | |||||
| saver.save(sess, $"{dataDir}/word_cnn.ckpt", global_step: step); | |||||
| print("Model is saved.\n"); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,218 +0,0 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using System.Security.Cryptography; | |||||
| using System.Text; | |||||
| using System.Text.RegularExpressions; | |||||
| using TensorFlowNET.Examples.Utility; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| public class DataHelpers | |||||
| { | |||||
| public static Dictionary<string, int> build_word_dict(string path) | |||||
| { | |||||
| var contents = File.ReadAllLines(path); | |||||
| var words = new List<string>(); | |||||
| foreach (var content in contents) | |||||
| words.AddRange(clean_str(content).Split(' ').Where(x => x.Length > 1)); | |||||
| var word_counter = words.GroupBy(x => x) | |||||
| .Select(x => new { Word = x.Key, Count = x.Count() }) | |||||
| .OrderByDescending(x => x.Count) | |||||
| .ToArray(); | |||||
| var word_dict = new Dictionary<string, int>(); | |||||
| word_dict["<pad>"] = 0; | |||||
| word_dict["<unk>"] = 1; | |||||
| word_dict["<eos>"] = 2; | |||||
| foreach (var word in word_counter) | |||||
| word_dict[word.Word] = word_dict.Count; | |||||
| return word_dict; | |||||
| } | |||||
| public static (int[][], int[]) build_word_dataset(string path, Dictionary<string, int> word_dict, int document_max_len) | |||||
| { | |||||
| var contents = File.ReadAllLines(path); | |||||
| var x = contents.Select(c => (clean_str(c) + " <eos>") | |||||
| .Split(' ').Take(document_max_len) | |||||
| .Select(w => word_dict.ContainsKey(w) ? word_dict[w] : word_dict["<unk>"]).ToArray()) | |||||
| .ToArray(); | |||||
| for (int i = 0; i < x.Length; i++) | |||||
| if (x[i].Length == document_max_len) | |||||
| x[i][document_max_len - 1] = word_dict["<eos>"]; | |||||
| else | |||||
| Array.Resize(ref x[i], document_max_len); | |||||
| var y = contents.Select(c => int.Parse(c.Substring(0, c.IndexOf(','))) - 1).ToArray(); | |||||
| return (x, y); | |||||
| } | |||||
| public static (int[][], int[], int) build_char_dataset(string path, string model, int document_max_len, int? limit = null, bool shuffle=true) | |||||
| { | |||||
| string alphabet = "abcdefghijklmnopqrstuvwxyz0123456789-,;.!?:’'\"/|_#$%ˆ&*˜‘+=<>()[]{} "; | |||||
| /*if (step == "train") | |||||
| df = pd.read_csv(TRAIN_PATH, names =["class", "title", "content"]);*/ | |||||
| var char_dict = new Dictionary<string, int>(); | |||||
| char_dict["<pad>"] = 0; | |||||
| char_dict["<unk>"] = 1; | |||||
| foreach (char c in alphabet) | |||||
| char_dict[c.ToString()] = char_dict.Count; | |||||
| var contents = File.ReadAllLines(path); | |||||
| if (shuffle) | |||||
| new Random(17).Shuffle(contents); | |||||
| //File.WriteAllLines("text_classification/dbpedia_csv/train_6400.csv", contents.Take(6400)); | |||||
| var size = limit == null ? contents.Length : limit.Value; | |||||
| var x = new int[size][]; | |||||
| var y = new int[size]; | |||||
| var tenth = size / 10; | |||||
| var percent = 0; | |||||
| for (int i = 0; i < size; i++) | |||||
| { | |||||
| if ((i + 1) % tenth == 0) | |||||
| { | |||||
| percent += 10; | |||||
| Console.WriteLine($"\t{percent}%"); | |||||
| } | |||||
| string[] parts = contents[i].ToLower().Split(",\"").ToArray(); | |||||
| string content = parts[2]; | |||||
| content = content.Substring(0, content.Length - 1); | |||||
| var a = new int[document_max_len]; | |||||
| for (int j = 0; j < document_max_len; j++) | |||||
| { | |||||
| if (j >= content.Length) | |||||
| a[j] = char_dict["<pad>"]; | |||||
| else | |||||
| a[j] = char_dict.ContainsKey(content[j].ToString()) ? char_dict[content[j].ToString()] : char_dict["<unk>"]; | |||||
| } | |||||
| x[i] = a; | |||||
| y[i] = int.Parse(parts[0]); | |||||
| } | |||||
| return (x, y, alphabet.Length + 2); | |||||
| } | |||||
| /// <summary> | |||||
| /// Loads MR polarity data from files, splits the data into words and generates labels. | |||||
| /// Returns split sentences and labels. | |||||
| /// </summary> | |||||
| /// <param name="positive_data_file"></param> | |||||
| /// <param name="negative_data_file"></param> | |||||
| /// <returns></returns> | |||||
| public static (string[], NDArray) load_data_and_labels(string positive_data_file, string negative_data_file) | |||||
| { | |||||
| Directory.CreateDirectory("CnnTextClassification"); | |||||
| Utility.Web.Download(positive_data_file, "CnnTextClassification", "rt -polarity.pos"); | |||||
| Utility.Web.Download(negative_data_file, "CnnTextClassification", "rt-polarity.neg"); | |||||
| // Load data from files | |||||
| var positive_examples = File.ReadAllLines("CnnTextClassification/rt-polarity.pos") | |||||
| .Select(x => x.Trim()) | |||||
| .ToArray(); | |||||
| var negative_examples = File.ReadAllLines("CnnTextClassification/rt-polarity.neg") | |||||
| .Select(x => x.Trim()) | |||||
| .ToArray(); | |||||
| var x_text = new List<string>(); | |||||
| x_text.AddRange(positive_examples); | |||||
| x_text.AddRange(negative_examples); | |||||
| x_text = x_text.Select(x => clean_str(x)).ToList(); | |||||
| var positive_labels = positive_examples.Select(x => new int[2] { 0, 1 }).ToArray(); | |||||
| var negative_labels = negative_examples.Select(x => new int[2] { 1, 0 }).ToArray(); | |||||
| var y = np.concatenate(new NDArray[] { new int[][][] { positive_labels, negative_labels } }); | |||||
| return (x_text.ToArray(), y); | |||||
| } | |||||
| private static string clean_str(string str) | |||||
| { | |||||
| str = Regex.Replace(str, "[^A-Za-z0-9(),!?]", " "); | |||||
| str = Regex.Replace(str, ",", " "); | |||||
| return str; | |||||
| } | |||||
| /// <summary> | |||||
| /// Padding | |||||
| /// </summary> | |||||
| /// <param name="sequences"></param> | |||||
| /// <param name="pad_tok">the char to pad with</param> | |||||
| /// <returns>a list of list where each sublist has same length</returns> | |||||
| public static (int[][], int[]) pad_sequences(int[][] sequences, int pad_tok = 0) | |||||
| { | |||||
| int max_length = sequences.Select(x => x.Length).Max(); | |||||
| return _pad_sequences(sequences, pad_tok, max_length); | |||||
| } | |||||
| public static (int[][][], int[][]) pad_sequences(int[][][] sequences, int pad_tok = 0) | |||||
| { | |||||
| int max_length_word = sequences.Select(x => x.Select(w => w.Length).Max()).Max(); | |||||
| int[][][] sequence_padded; | |||||
| var sequence_length = new int[sequences.Length][]; | |||||
| for (int i = 0; i < sequences.Length; i++) | |||||
| { | |||||
| // all words are same length now | |||||
| var (sp, sl) = _pad_sequences(sequences[i], pad_tok, max_length_word); | |||||
| sequence_length[i] = sl; | |||||
| } | |||||
| int max_length_sentence = sequences.Select(x => x.Length).Max(); | |||||
| (sequence_padded, _) = _pad_sequences(sequences, np.repeat(pad_tok, max_length_word).GetData<int>().ToArray(), max_length_sentence); | |||||
| (sequence_length, _) = _pad_sequences(sequence_length, 0, max_length_sentence); | |||||
| return (sequence_padded, sequence_length); | |||||
| } | |||||
| private static (int[][], int[]) _pad_sequences(int[][] sequences, int pad_tok, int max_length) | |||||
| { | |||||
| var sequence_length = new int[sequences.Length]; | |||||
| for (int i = 0; i < sequences.Length; i++) | |||||
| { | |||||
| sequence_length[i] = sequences[i].Length; | |||||
| Array.Resize(ref sequences[i], max_length); | |||||
| } | |||||
| return (sequences, sequence_length); | |||||
| } | |||||
| private static (int[][][], int[]) _pad_sequences(int[][][] sequences, int[] pad_tok, int max_length) | |||||
| { | |||||
| var sequence_length = new int[sequences.Length]; | |||||
| for (int i = 0; i < sequences.Length; i++) | |||||
| { | |||||
| sequence_length[i] = sequences[i].Length; | |||||
| Array.Resize(ref sequences[i], max_length); | |||||
| for (int j = 0; j < max_length - sequence_length[i]; j++) | |||||
| { | |||||
| sequences[i][max_length - j - 1] = new int[pad_tok.Length]; | |||||
| Array.Copy(pad_tok, sequences[i][max_length - j - 1], pad_tok.Length); | |||||
| } | |||||
| } | |||||
| return (sequences, sequence_length); | |||||
| } | |||||
| public static string CalculateMD5Hash(string input) | |||||
| { | |||||
| // step 1, calculate MD5 hash from input | |||||
| MD5 md5 = System.Security.Cryptography.MD5.Create(); | |||||
| byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input); | |||||
| byte[] hash = md5.ComputeHash(inputBytes); | |||||
| // step 2, convert byte array to hex string | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| for (int i = 0; i < hash.Length; i++) | |||||
| { | |||||
| sb.Append(hash[i].ToString("X2")); | |||||
| } | |||||
| return sb.ToString(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,59 +0,0 @@ | |||||
| using System; | |||||
| using System.IO; | |||||
| using Tensorflow; | |||||
| using Tensorflow.Estimators; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Bidirectional LSTM-CRF Models for Sequence Tagging | |||||
| /// https://github.com/guillaumegenthial/tf_ner/tree/master/models/lstm_crf | |||||
| /// </summary> | |||||
| public class BiLstmCrfNer : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = false; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public string Name => "bi-LSTM + CRF NER"; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| return false; | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| var hp = new HyperParams("BiLstmCrfNer"); | |||||
| hp.filepath_words = Path.Combine(hp.data_root_dir, "vocab.words.txt"); | |||||
| hp.filepath_chars = Path.Combine(hp.data_root_dir, "vocab.chars.txt"); | |||||
| hp.filepath_tags = Path.Combine(hp.data_root_dir, "vocab.tags.txt"); | |||||
| hp.filepath_glove = Path.Combine(hp.data_root_dir, "glove.npz"); | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,55 +0,0 @@ | |||||
| using System; | |||||
| using Tensorflow; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// The CRF module implements a linear-chain CRF layer for learning to predict tag sequences. | |||||
| /// This variant of the CRF is factored into unary potentials for every element | |||||
| /// in the sequence and binary potentials for every transition between output tags. | |||||
| /// | |||||
| /// tensorflow\contrib\crf\python\ops\crf.py | |||||
| /// </summary> | |||||
| public class CRF : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public string Name => "CRF"; | |||||
| public bool Run() | |||||
| { | |||||
| return true; | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,233 +0,0 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using Tensorflow; | |||||
| using Tensorflow.Estimators; | |||||
| using TensorFlowNET.Examples.Utility; | |||||
| using static Tensorflow.Binding; | |||||
| using static TensorFlowNET.Examples.DataHelpers; | |||||
| namespace TensorFlowNET.Examples.Text.NER | |||||
| { | |||||
| /// <summary> | |||||
| /// A NER model using Tensorflow (LSTM + CRF + chars embeddings). | |||||
| /// State-of-the-art performance (F1 score between 90 and 91). | |||||
| /// | |||||
| /// https://github.com/guillaumegenthial/sequence_tagging | |||||
| /// </summary> | |||||
| public class LstmCrfNer : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public bool IsImportingGraph { get; set; } = true; | |||||
| public string Name => "LSTM + CRF NER"; | |||||
| HyperParams hp; | |||||
| int nwords, nchars, ntags; | |||||
| CoNLLDataset dev, train; | |||||
| Tensor word_ids_tensor; | |||||
| Tensor sequence_lengths_tensor; | |||||
| Tensor char_ids_tensor; | |||||
| Tensor word_lengths_tensor; | |||||
| Tensor labels_tensor; | |||||
| Tensor dropout_tensor; | |||||
| Tensor lr_tensor; | |||||
| Operation train_op; | |||||
| Tensor loss; | |||||
| Tensor merged; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| var graph = tf.Graph().as_default(); | |||||
| tf.train.import_meta_graph("graph/lstm_crf_ner.meta"); | |||||
| float loss_value = 0f; | |||||
| //add_summary(); | |||||
| word_ids_tensor = graph.OperationByName("word_ids"); | |||||
| sequence_lengths_tensor = graph.OperationByName("sequence_lengths"); | |||||
| char_ids_tensor = graph.OperationByName("char_ids"); | |||||
| word_lengths_tensor = graph.OperationByName("word_lengths"); | |||||
| labels_tensor = graph.OperationByName("labels"); | |||||
| dropout_tensor = graph.OperationByName("dropout"); | |||||
| lr_tensor = graph.OperationByName("lr"); | |||||
| train_op = graph.OperationByName("train_step/Adam"); | |||||
| loss = graph.OperationByName("Mean"); | |||||
| //merged = graph.OperationByName("Merge/MergeSummary"); | |||||
| var init = tf.global_variables_initializer(); | |||||
| using (var sess = tf.Session()) | |||||
| { | |||||
| sess.run(init); | |||||
| foreach (var epoch in range(hp.epochs)) | |||||
| { | |||||
| Console.Write($"Epoch {epoch + 1} out of {hp.epochs}, "); | |||||
| loss_value = run_epoch(sess, train, dev, epoch); | |||||
| print($"train loss: {loss_value}"); | |||||
| } | |||||
| } | |||||
| return loss_value < 0.1; | |||||
| } | |||||
| private float run_epoch(Session sess, CoNLLDataset train, CoNLLDataset dev, int epoch) | |||||
| { | |||||
| float accuracy = 0; | |||||
| // iterate over dataset | |||||
| var batches = minibatches(train, hp.batch_size); | |||||
| foreach (var(words, labels) in batches) | |||||
| { | |||||
| var (fd, _) = get_feed_dict(words, labels, hp.lr, hp.dropout); | |||||
| (_, accuracy) = sess.run((train_op, loss), feed_dict: fd); | |||||
| } | |||||
| return accuracy; | |||||
| } | |||||
| private IEnumerable<((int[][], int[])[], int[][])> minibatches(CoNLLDataset data, int minibatch_size) | |||||
| { | |||||
| var x_batch = new List<(int[][], int[])>(); | |||||
| var y_batch = new List<int[]>(); | |||||
| foreach(var (x, y) in data.GetItems()) | |||||
| { | |||||
| if (len(y_batch) == minibatch_size) | |||||
| { | |||||
| yield return (x_batch.ToArray(), y_batch.ToArray()); | |||||
| x_batch.Clear(); | |||||
| y_batch.Clear(); | |||||
| } | |||||
| var x3 = (x.Select(x1 => x1.Item1).ToArray(), x.Select(x2 => x2.Item2).ToArray()); | |||||
| x_batch.Add(x3); | |||||
| y_batch.Add(y); | |||||
| } | |||||
| if (len(y_batch) > 0) | |||||
| yield return (x_batch.ToArray(), y_batch.ToArray()); | |||||
| } | |||||
| /// <summary> | |||||
| /// Given some data, pad it and build a feed dictionary | |||||
| /// </summary> | |||||
| /// <param name="words"> | |||||
| /// list of sentences. A sentence is a list of ids of a list of | |||||
| /// words. A word is a list of ids | |||||
| /// </param> | |||||
| /// <param name="labels">list of ids</param> | |||||
| /// <param name="lr">learning rate</param> | |||||
| /// <param name="dropout">keep prob</param> | |||||
| private (FeedItem[], int[]) get_feed_dict((int[][], int[])[] words, int[][] labels, float lr = 0f, float dropout = 0f) | |||||
| { | |||||
| int[] sequence_lengths; | |||||
| int[][] word_lengths; | |||||
| int[][] word_ids; | |||||
| int[][][] char_ids; | |||||
| if (true) // use_chars | |||||
| { | |||||
| (char_ids, word_ids) = (words.Select(x => x.Item1).ToArray(), words.Select(x => x.Item2).ToArray()); | |||||
| (word_ids, sequence_lengths) = pad_sequences(word_ids, pad_tok: 0); | |||||
| (char_ids, word_lengths) = pad_sequences(char_ids, pad_tok: 0); | |||||
| } | |||||
| // build feed dictionary | |||||
| var feeds = new List<FeedItem>(); | |||||
| feeds.Add(new FeedItem(word_ids_tensor, np.array(word_ids))); | |||||
| feeds.Add(new FeedItem(sequence_lengths_tensor, np.array(sequence_lengths))); | |||||
| if(true) // use_chars | |||||
| { | |||||
| feeds.Add(new FeedItem(char_ids_tensor, np.array(char_ids))); | |||||
| feeds.Add(new FeedItem(word_lengths_tensor, np.array(word_lengths))); | |||||
| } | |||||
| (labels, _) = pad_sequences(labels, 0); | |||||
| feeds.Add(new FeedItem(labels_tensor, np.array(labels))); | |||||
| feeds.Add(new FeedItem(lr_tensor, lr)); | |||||
| feeds.Add(new FeedItem(dropout_tensor, dropout)); | |||||
| return (feeds.ToArray(), sequence_lengths); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| hp = new HyperParams("LstmCrfNer") | |||||
| { | |||||
| epochs = 50, | |||||
| dropout = 0.5f, | |||||
| batch_size = 20, | |||||
| lr_method = "adam", | |||||
| lr = 0.001f, | |||||
| lr_decay = 0.9f, | |||||
| clip = false, | |||||
| epoch_no_imprv = 3, | |||||
| hidden_size_char = 100, | |||||
| hidden_size_lstm = 300 | |||||
| }; | |||||
| hp.filepath_dev = hp.filepath_test = hp.filepath_train = Path.Combine(hp.data_root_dir, "test.txt"); | |||||
| // Loads vocabulary, processing functions and embeddings | |||||
| hp.filepath_words = Path.Combine(hp.data_root_dir, "words.txt"); | |||||
| hp.filepath_tags = Path.Combine(hp.data_root_dir, "tags.txt"); | |||||
| hp.filepath_chars = Path.Combine(hp.data_root_dir, "chars.txt"); | |||||
| string url = "https://raw.githubusercontent.com/SciSharp/TensorFlow.NET/master/data/lstm_crf_ner.zip"; | |||||
| Web.Download(url, hp.data_root_dir, "lstm_crf_ner.zip"); | |||||
| Compress.UnZip(Path.Combine(hp.data_root_dir, "lstm_crf_ner.zip"), hp.data_root_dir); | |||||
| // 1. vocabulary | |||||
| /*vocab_tags = load_vocab(hp.filepath_tags); | |||||
| nwords = vocab_words.Count; | |||||
| nchars = vocab_chars.Count; | |||||
| ntags = vocab_tags.Count;*/ | |||||
| // 2. get processing functions that map str -> id | |||||
| dev = new CoNLLDataset(hp.filepath_dev, hp); | |||||
| train = new CoNLLDataset(hp.filepath_train, hp); | |||||
| // download graph meta data | |||||
| var meta_file = "lstm_crf_ner.meta"; | |||||
| var meta_path = Path.Combine("graph", meta_file); | |||||
| url = "https://raw.githubusercontent.com/SciSharp/TensorFlow.NET/master/graph/" + meta_file; | |||||
| Web.Download(url, "graph", meta_file); | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,51 +0,0 @@ | |||||
| using System; | |||||
| using Tensorflow; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// https://github.com/guillaumegenthial/tf_ner | |||||
| /// </summary> | |||||
| public class NamedEntityRecognition : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = false; | |||||
| public string Name => "NER"; | |||||
| public bool IsImportingGraph { get; set; } = false; | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public bool Run() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,243 +0,0 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using Tensorflow; | |||||
| using TensorFlowNET.Examples.Utility; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples | |||||
| { | |||||
| /// <summary> | |||||
| /// Implement Word2Vec algorithm to compute vector representations of words. | |||||
| /// https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/2_BasicModels/word2vec.py | |||||
| /// </summary> | |||||
| public class Word2Vec : IExample | |||||
| { | |||||
| public bool Enabled { get; set; } = true; | |||||
| public string Name => "Word2Vec"; | |||||
| public bool IsImportingGraph { get; set; } = true; | |||||
| // Training Parameters | |||||
| float learning_rate = 0.1f; | |||||
| int batch_size = 128; | |||||
| int num_steps = 30000; //3000000; | |||||
| int display_step = 1000; //10000; | |||||
| int eval_step = 5000;//200000; | |||||
| // Evaluation Parameters | |||||
| string[] eval_words = new string[] { "five", "of", "going", "hardware", "american", "britain" }; | |||||
| string[] text_words; | |||||
| List<WordId> word2id; | |||||
| int[] data; | |||||
| // Word2Vec Parameters | |||||
| int embedding_size = 200; // Dimension of the embedding vector | |||||
| int max_vocabulary_size = 50000; // Total number of different words in the vocabulary | |||||
| int min_occurrence = 10; // Remove all words that does not appears at least n times | |||||
| int skip_window = 3; // How many words to consider left and right | |||||
| int num_skips = 2; // How many times to reuse an input to generate a label | |||||
| int num_sampled = 64; // Number of negative examples to sample | |||||
| int data_index = 0; | |||||
| int top_k = 8; // number of nearest neighbors | |||||
| float average_loss = 0; | |||||
| public bool Run() | |||||
| { | |||||
| PrepareData(); | |||||
| var graph = tf.Graph().as_default(); | |||||
| tf.train.import_meta_graph($"graph{Path.DirectorySeparatorChar}word2vec.meta"); | |||||
| // Input data | |||||
| Tensor X = graph.OperationByName("Placeholder"); | |||||
| // Input label | |||||
| Tensor Y = graph.OperationByName("Placeholder_1"); | |||||
| // Compute the average NCE loss for the batch | |||||
| Tensor loss_op = graph.OperationByName("Mean"); | |||||
| // Define the optimizer | |||||
| var train_op = graph.OperationByName("GradientDescent"); | |||||
| Tensor cosine_sim_op = graph.OperationByName("MatMul_1"); | |||||
| // Initialize the variables (i.e. assign their default value) | |||||
| var init = tf.global_variables_initializer(); | |||||
| using (var sess = tf.Session(graph)) | |||||
| { | |||||
| // Run the initializer | |||||
| sess.run(init); | |||||
| var x_test = (from word in eval_words | |||||
| join id in word2id on word equals id.Word into wi | |||||
| from wi2 in wi.DefaultIfEmpty() | |||||
| select wi2 == null ? 0 : wi2.Id).ToArray(); | |||||
| foreach (var step in range(1, num_steps + 1)) | |||||
| { | |||||
| // Get a new batch of data | |||||
| var (batch_x, batch_y) = next_batch(batch_size, num_skips, skip_window); | |||||
| (_, float loss) = sess.run((train_op, loss_op), (X, batch_x), (Y, batch_y)); | |||||
| average_loss += loss; | |||||
| if (step % display_step == 0 || step == 1) | |||||
| { | |||||
| if (step > 1) | |||||
| average_loss /= display_step; | |||||
| print($"Step {step}, Average Loss= {average_loss.ToString("F4")}"); | |||||
| average_loss = 0; | |||||
| } | |||||
| // Evaluation | |||||
| if (step % eval_step == 0 || step == 1) | |||||
| { | |||||
| print("Evaluation..."); | |||||
| var sim = sess.run(cosine_sim_op, (X, x_test)); | |||||
| foreach(var i in range(len(eval_words))) | |||||
| { | |||||
| var nearest = (0f - sim[i]).argsort<float>() | |||||
| .Data<int>() | |||||
| .Skip(1) | |||||
| .Take(top_k) | |||||
| .ToArray(); | |||||
| string log_str = $"\"{eval_words[i]}\" nearest neighbors:"; | |||||
| foreach (var k in range(top_k)) | |||||
| log_str = $"{log_str} {word2id.First(x => x.Id == nearest[k]).Word},"; | |||||
| print(log_str); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| return average_loss < 100; | |||||
| } | |||||
| // Generate training batch for the skip-gram model | |||||
| private (NDArray, NDArray) next_batch(int batch_size, int num_skips, int skip_window) | |||||
| { | |||||
| var batch = np.ndarray(new Shape(batch_size), dtype: np.int32); | |||||
| var labels = np.ndarray((batch_size, 1), dtype: np.int32); | |||||
| // get window size (words left and right + current one) | |||||
| int span = 2 * skip_window + 1; | |||||
| var buffer = new Queue<int>(span); | |||||
| if (data_index + span > data.Length) | |||||
| data_index = 0; | |||||
| data.Skip(data_index).Take(span).ToList().ForEach(x => buffer.Enqueue(x)); | |||||
| data_index += span; | |||||
| foreach (var i in range(batch_size / num_skips)) | |||||
| { | |||||
| var context_words = range(span).Where(x => x != skip_window).ToArray(); | |||||
| var words_to_use = new int[] { 1, 6 }; | |||||
| foreach(var (j, context_word) in enumerate(words_to_use)) | |||||
| { | |||||
| batch[i * num_skips + j] = buffer.ElementAt(skip_window); | |||||
| labels[i * num_skips + j, 0] = buffer.ElementAt(context_word); | |||||
| } | |||||
| if (data_index == len(data)) | |||||
| { | |||||
| //buffer.extend(data[0:span]); | |||||
| data_index = span; | |||||
| } | |||||
| else | |||||
| { | |||||
| buffer.Enqueue(data[data_index]); | |||||
| data_index += 1; | |||||
| } | |||||
| } | |||||
| // Backtrack a little bit to avoid skipping words in the end of a batch | |||||
| data_index = (data_index + len(data) - span) % len(data); | |||||
| return (batch, labels); | |||||
| } | |||||
| public void PrepareData() | |||||
| { | |||||
| // Download graph meta | |||||
| var url = "https://github.com/SciSharp/TensorFlow.NET/raw/master/graph/word2vec.meta"; | |||||
| Web.Download(url, "graph", "word2vec.meta"); | |||||
| // Download a small chunk of Wikipedia articles collection | |||||
| url = "https://raw.githubusercontent.com/SciSharp/TensorFlow.NET/master/data/text8.zip"; | |||||
| Web.Download(url, "word2vec", "text8.zip"); | |||||
| // Unzip the dataset file. Text has already been processed | |||||
| Compress.UnZip($"word2vec{Path.DirectorySeparatorChar}text8.zip", "word2vec"); | |||||
| int wordId = 0; | |||||
| text_words = File.ReadAllText($"word2vec{Path.DirectorySeparatorChar}text8").Trim().ToLower().Split(); | |||||
| // Build the dictionary and replace rare words with UNK token | |||||
| word2id = text_words.GroupBy(x => x) | |||||
| .Select(x => new WordId | |||||
| { | |||||
| Word = x.Key, | |||||
| Occurrence = x.Count() | |||||
| }) | |||||
| .Where(x => x.Occurrence >= min_occurrence) // Remove samples with less than 'min_occurrence' occurrences | |||||
| .OrderByDescending(x => x.Occurrence) // Retrieve the most common words | |||||
| .Select(x => new WordId | |||||
| { | |||||
| Word = x.Word, | |||||
| Id = ++wordId, // Assign an id to each word | |||||
| Occurrence = x.Occurrence | |||||
| }) | |||||
| .ToList(); | |||||
| // Retrieve a word id, or assign it index 0 ('UNK') if not in dictionary | |||||
| data = (from word in text_words | |||||
| join id in word2id on word equals id.Word into wi | |||||
| from wi2 in wi.DefaultIfEmpty() | |||||
| select wi2 == null ? 0 : wi2.Id).ToArray(); | |||||
| word2id.Insert(0, new WordId { Word = "UNK", Id = 0, Occurrence = data.Count(x => x == 0) }); | |||||
| print($"Words count: {text_words.Length}"); | |||||
| print($"Unique words: {text_words.Distinct().Count()}"); | |||||
| print($"Vocabulary size: {word2id.Count}"); | |||||
| print($"Most common words: {string.Join(", ", word2id.Take(10))}"); | |||||
| } | |||||
| public Graph ImportGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public Graph BuildGraph() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Train(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Predict(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public void Test(Session sess) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| private class WordId | |||||
| { | |||||
| public string Word { get; set; } | |||||
| public int Id { get; set; } | |||||
| public int Occurrence { get; set; } | |||||
| public override string ToString() | |||||
| { | |||||
| return Word + " " + Id + " " + Occurrence; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,147 +0,0 @@ | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples.Text | |||||
| { | |||||
| public class CharCnn : ITextModel | |||||
| { | |||||
| public CharCnn(int alphabet_size, int document_max_len, int num_class) | |||||
| { | |||||
| var learning_rate = 0.001f; | |||||
| var filter_sizes = new int[] { 7, 7, 3, 3, 3, 3 }; | |||||
| var num_filters = 256; | |||||
| var kernel_initializer = tf.truncated_normal_initializer(stddev: 0.05f); | |||||
| var x = tf.placeholder(tf.int32, new TensorShape(-1, document_max_len), name: "x"); | |||||
| var y = tf.placeholder(tf.int32, new TensorShape(-1), name: "y"); | |||||
| var is_training = tf.placeholder(tf.@bool, new TensorShape(), name: "is_training"); | |||||
| var global_step = tf.Variable(0, trainable: false); | |||||
| var keep_prob = tf.where(is_training, 0.5f, 1.0f); | |||||
| var x_one_hot = tf.one_hot(x, alphabet_size); | |||||
| var x_expanded = tf.expand_dims(x_one_hot, -1); | |||||
| // ============= Convolutional Layers ============= | |||||
| Tensor pool1 = null, pool2 = null; | |||||
| Tensor conv3 = null, conv4 = null, conv5 = null, conv6 = null; | |||||
| Tensor h_pool = null; | |||||
| tf_with(tf.name_scope("conv-maxpool-1"), delegate | |||||
| { | |||||
| var conv1 = tf.layers.conv2d(x_expanded, | |||||
| filters: num_filters, | |||||
| kernel_size: new[] { filter_sizes[0], alphabet_size }, | |||||
| kernel_initializer: kernel_initializer, | |||||
| activation: tf.nn.relu()); | |||||
| pool1 = tf.layers.max_pooling2d(conv1, | |||||
| pool_size: new[] { 3, 1 }, | |||||
| strides: new[] { 3, 1 }); | |||||
| pool1 = tf.transpose(pool1, new[] { 0, 1, 3, 2 }); | |||||
| }); | |||||
| tf_with(tf.name_scope("conv-maxpool-2"), delegate | |||||
| { | |||||
| var conv2 = tf.layers.conv2d(pool1, | |||||
| filters: num_filters, | |||||
| kernel_size: new[] {filter_sizes[1], num_filters }, | |||||
| kernel_initializer: kernel_initializer, | |||||
| activation: tf.nn.relu()); | |||||
| pool2 = tf.layers.max_pooling2d(conv2, | |||||
| pool_size: new[] { 3, 1 }, | |||||
| strides: new[] { 3, 1 }); | |||||
| pool2 = tf.transpose(pool2, new[] { 0, 1, 3, 2 }); | |||||
| }); | |||||
| tf_with(tf.name_scope("conv-3"), delegate | |||||
| { | |||||
| conv3 = tf.layers.conv2d(pool2, | |||||
| filters: num_filters, | |||||
| kernel_size: new[] { filter_sizes[2], num_filters }, | |||||
| kernel_initializer: kernel_initializer, | |||||
| activation: tf.nn.relu()); | |||||
| conv3 = tf.transpose(conv3, new[] { 0, 1, 3, 2 }); | |||||
| }); | |||||
| tf_with(tf.name_scope("conv-4"), delegate | |||||
| { | |||||
| conv4 = tf.layers.conv2d(conv3, | |||||
| filters: num_filters, | |||||
| kernel_size: new[] { filter_sizes[3], num_filters }, | |||||
| kernel_initializer: kernel_initializer, | |||||
| activation: tf.nn.relu()); | |||||
| conv4 = tf.transpose(conv4, new[] { 0, 1, 3, 2 }); | |||||
| }); | |||||
| tf_with(tf.name_scope("conv-5"), delegate | |||||
| { | |||||
| conv5 = tf.layers.conv2d(conv4, | |||||
| filters: num_filters, | |||||
| kernel_size: new[] { filter_sizes[4], num_filters }, | |||||
| kernel_initializer: kernel_initializer, | |||||
| activation: tf.nn.relu()); | |||||
| conv5 = tf.transpose(conv5, new[] { 0, 1, 3, 2 }); | |||||
| }); | |||||
| tf_with(tf.name_scope("conv-maxpool-6"), delegate | |||||
| { | |||||
| conv6 = tf.layers.conv2d(conv5, | |||||
| filters: num_filters, | |||||
| kernel_size: new[] { filter_sizes[5], num_filters }, | |||||
| kernel_initializer: kernel_initializer, | |||||
| activation: tf.nn.relu()); | |||||
| var pool6 = tf.layers.max_pooling2d(conv6, | |||||
| pool_size: new[] { 3, 1 }, | |||||
| strides: new[] { 3, 1 }); | |||||
| pool6 = tf.transpose(pool6, new[] { 0, 2, 1, 3 }); | |||||
| h_pool = tf.reshape(pool6, new[] { -1, 34 * num_filters }); | |||||
| }); | |||||
| // ============= Fully Connected Layers ============= | |||||
| Tensor fc1_out = null, fc2_out = null; | |||||
| Tensor logits = null; | |||||
| Tensor predictions = null; | |||||
| tf_with(tf.name_scope("fc-1"), delegate | |||||
| { | |||||
| fc1_out = tf.layers.dense(h_pool, | |||||
| 1024, | |||||
| activation: tf.nn.relu(), | |||||
| kernel_initializer: kernel_initializer); | |||||
| }); | |||||
| tf_with(tf.name_scope("fc-2"), delegate | |||||
| { | |||||
| fc2_out = tf.layers.dense(fc1_out, | |||||
| 1024, | |||||
| activation: tf.nn.relu(), | |||||
| kernel_initializer: kernel_initializer); | |||||
| }); | |||||
| tf_with(tf.name_scope("fc-3"), delegate | |||||
| { | |||||
| logits = tf.layers.dense(fc2_out, | |||||
| num_class, | |||||
| kernel_initializer: kernel_initializer); | |||||
| predictions = tf.argmax(logits, -1, output_type: tf.int32); | |||||
| }); | |||||
| tf_with(tf.name_scope("loss"), delegate | |||||
| { | |||||
| var y_one_hot = tf.one_hot(y, num_class); | |||||
| var loss = tf.reduce_mean( | |||||
| tf.nn.softmax_cross_entropy_with_logits_v2(logits: logits, labels: y_one_hot)); | |||||
| var optimizer = tf.train.AdamOptimizer(learning_rate).minimize(loss, global_step: global_step); | |||||
| }); | |||||
| tf_with(tf.name_scope("accuracy"), delegate | |||||
| { | |||||
| var correct_predictions = tf.equal(predictions, y); | |||||
| var accuracy = tf.reduce_mean(tf.cast(correct_predictions, tf.float32), name: "accuracy"); | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,6 +0,0 @@ | |||||
| namespace TensorFlowNET.Examples.Text | |||||
| { | |||||
| interface ITextModel | |||||
| { | |||||
| } | |||||
| } | |||||
| @@ -1,171 +0,0 @@ | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples.Text | |||||
| { | |||||
| public class VdCnn : ITextModel | |||||
| { | |||||
| private int embedding_size; | |||||
| private int[] filter_sizes; | |||||
| private int[] num_filters; | |||||
| private int[] num_blocks; | |||||
| private float learning_rate; | |||||
| private IInitializer cnn_initializer; | |||||
| private IInitializer fc_initializer; | |||||
| public Tensor x { get; private set; } | |||||
| public Tensor y { get; private set; } | |||||
| public Tensor is_training { get; private set; } | |||||
| private RefVariable global_step; | |||||
| private RefVariable embeddings; | |||||
| private Tensor x_emb; | |||||
| private Tensor x_expanded; | |||||
| private Tensor logits; | |||||
| private Tensor predictions; | |||||
| private Tensor loss; | |||||
| public VdCnn(int alphabet_size, int document_max_len, int num_class) | |||||
| { | |||||
| embedding_size = 16; | |||||
| filter_sizes = new int[] { 3, 3, 3, 3, 3 }; | |||||
| num_filters = new int[] { 64, 64, 128, 256, 512 }; | |||||
| num_blocks = new int[] { 2, 2, 2, 2 }; | |||||
| learning_rate = 0.001f; | |||||
| cnn_initializer = tensorflow.keras.initializers.he_normal(); | |||||
| fc_initializer = tf.truncated_normal_initializer(stddev: 0.05f); | |||||
| x = tf.placeholder(tf.int32, new TensorShape(-1, document_max_len), name: "x"); | |||||
| y = tf.placeholder(tf.int32, new TensorShape(-1), name: "y"); | |||||
| is_training = tf.placeholder(tf.@bool, new TensorShape(), name: "is_training"); | |||||
| global_step = tf.Variable(0, trainable: false); | |||||
| // Embedding Layer | |||||
| tf_with(tf.name_scope("embedding"), delegate | |||||
| { | |||||
| var init_embeddings = tf.random_uniform(new int[] { alphabet_size, embedding_size }, -1.0f, 1.0f); | |||||
| embeddings = tf.get_variable("embeddings", initializer: init_embeddings); | |||||
| x_emb = tf.nn.embedding_lookup(embeddings, x); | |||||
| x_expanded = tf.expand_dims(x_emb, -1); | |||||
| }); | |||||
| Tensor conv0 = null; | |||||
| Tensor conv1 = null; | |||||
| Tensor conv2 = null; | |||||
| Tensor conv3 = null; | |||||
| Tensor conv4 = null; | |||||
| Tensor h_flat = null; | |||||
| Tensor fc1_out = null; | |||||
| Tensor fc2_out = null; | |||||
| // First Convolution Layer | |||||
| tf_with(tf.variable_scope("conv-0"), delegate | |||||
| { | |||||
| conv0 = tf.layers.conv2d(x_expanded, | |||||
| filters: num_filters[0], | |||||
| kernel_size: new int[] { filter_sizes[0], embedding_size }, | |||||
| kernel_initializer: cnn_initializer, | |||||
| activation: tf.nn.relu()); | |||||
| conv0 = tf.transpose(conv0, new int[] { 0, 1, 3, 2 }); | |||||
| }); | |||||
| tf_with(tf.name_scope("conv-block-1"), delegate { | |||||
| conv1 = conv_block(conv0, 1); | |||||
| }); | |||||
| tf_with(tf.name_scope("conv-block-2"), delegate { | |||||
| conv2 = conv_block(conv1, 2); | |||||
| }); | |||||
| tf_with(tf.name_scope("conv-block-3"), delegate { | |||||
| conv3 = conv_block(conv2, 3); | |||||
| }); | |||||
| tf_with(tf.name_scope("conv-block-4"), delegate | |||||
| { | |||||
| conv4 = conv_block(conv3, 4, max_pool: false); | |||||
| }); | |||||
| // ============= k-max Pooling ============= | |||||
| tf_with(tf.name_scope("k-max-pooling"), delegate | |||||
| { | |||||
| var h = tf.transpose(tf.squeeze(conv4, new int[] { -1 }), new int[] { 0, 2, 1 }); | |||||
| var top_k = tf.nn.top_k(h, k: 8, sorted: false)[0]; | |||||
| h_flat = tf.reshape(top_k, new int[] { -1, 512 * 8 }); | |||||
| }); | |||||
| // ============= Fully Connected Layers ============= | |||||
| tf_with(tf.name_scope("fc-1"), scope => | |||||
| { | |||||
| fc1_out = tf.layers.dense(h_flat, 2048, activation: tf.nn.relu(), kernel_initializer: fc_initializer); | |||||
| }); | |||||
| tf_with(tf.name_scope("fc-2"), scope => | |||||
| { | |||||
| fc2_out = tf.layers.dense(fc1_out, 2048, activation: tf.nn.relu(), kernel_initializer: fc_initializer); | |||||
| }); | |||||
| tf_with(tf.name_scope("fc-3"), scope => | |||||
| { | |||||
| logits = tf.layers.dense(fc2_out, num_class, activation: null, kernel_initializer: fc_initializer); | |||||
| predictions = tf.argmax(logits, -1, output_type: tf.int32); | |||||
| }); | |||||
| // ============= Loss and Accuracy ============= | |||||
| tf_with(tf.name_scope("loss"), delegate | |||||
| { | |||||
| var y_one_hot = tf.one_hot(y, num_class); | |||||
| loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits: logits, labels: y_one_hot)); | |||||
| var update_ops = tf.get_collection<object>(tf.GraphKeys.UPDATE_OPS); | |||||
| tf_with(tf.control_dependencies(update_ops.Select(x => (Operation)x).ToArray()), delegate | |||||
| { | |||||
| var adam = tf.train.AdamOptimizer(learning_rate); | |||||
| adam.minimize(loss, global_step: global_step); | |||||
| }); | |||||
| }); | |||||
| } | |||||
| private Tensor conv_block(Tensor input, int i, bool max_pool = true) | |||||
| { | |||||
| return tf_with(tf.variable_scope($"conv-block-{i}"), delegate | |||||
| { | |||||
| Tensor conv = null; | |||||
| // Two "conv-batch_norm-relu" layers. | |||||
| foreach (var j in Enumerable.Range(0, 2)) | |||||
| { | |||||
| tf_with(tf.variable_scope($"conv-{j}"), delegate | |||||
| { | |||||
| // convolution | |||||
| conv = tf.layers.conv2d( | |||||
| input, | |||||
| filters: num_filters[i], | |||||
| kernel_size: new int[] { filter_sizes[i], num_filters[i - 1] }, | |||||
| kernel_initializer: cnn_initializer, | |||||
| activation: null); | |||||
| // batch normalization | |||||
| conv = tf.layers.batch_normalization(conv, training: is_training); | |||||
| // relu | |||||
| conv = tf.nn.relu(conv); | |||||
| conv = tf.transpose(conv, new int[] { 0, 1, 3, 2 }); | |||||
| }); | |||||
| } | |||||
| if (max_pool) | |||||
| { | |||||
| // Max pooling | |||||
| return tf.layers.max_pooling2d( | |||||
| conv, | |||||
| pool_size: new int[] { 3, 1 }, | |||||
| strides: new int[] { 2, 1 }, | |||||
| padding: "SAME"); | |||||
| } | |||||
| else | |||||
| { | |||||
| return conv; | |||||
| } | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,99 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using System.Collections.Generic; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.Examples.Text | |||||
| { | |||||
| public class WordCnn : ITextModel | |||||
| { | |||||
| public WordCnn(int vocabulary_size, int document_max_len, int num_class) | |||||
| { | |||||
| var embedding_size = 128; | |||||
| var learning_rate = 0.001f; | |||||
| var filter_sizes = new int[3, 4, 5]; | |||||
| var num_filters = 100; | |||||
| var x = tf.placeholder(tf.int32, new TensorShape(-1, document_max_len), name: "x"); | |||||
| var y = tf.placeholder(tf.int32, new TensorShape(-1), name: "y"); | |||||
| var is_training = tf.placeholder(tf.@bool, new TensorShape(), name: "is_training"); | |||||
| var global_step = tf.Variable(0, trainable: false); | |||||
| var keep_prob = tf.where(is_training, 0.5f, 1.0f); | |||||
| Tensor x_emb = null; | |||||
| tf_with(tf.name_scope("embedding"), scope => | |||||
| { | |||||
| var init_embeddings = tf.random_uniform(new int[] { vocabulary_size, embedding_size }); | |||||
| var embeddings = tf.get_variable("embeddings", initializer: init_embeddings); | |||||
| x_emb = tf.nn.embedding_lookup(embeddings, x); | |||||
| x_emb = tf.expand_dims(x_emb, -1); | |||||
| }); | |||||
| var pooled_outputs = new List<Tensor>(); | |||||
| for (int len = 0; len < filter_sizes.Rank; len++) | |||||
| { | |||||
| int filter_size = filter_sizes.GetLength(len); | |||||
| var conv = tf.layers.conv2d( | |||||
| x_emb, | |||||
| filters: num_filters, | |||||
| kernel_size: new int[] { filter_size, embedding_size }, | |||||
| strides: new int[] { 1, 1 }, | |||||
| padding: "VALID", | |||||
| activation: tf.nn.relu()); | |||||
| var pool = tf.layers.max_pooling2d( | |||||
| conv, | |||||
| pool_size: new[] { document_max_len - filter_size + 1, 1 }, | |||||
| strides: new[] { 1, 1 }, | |||||
| padding: "VALID"); | |||||
| pooled_outputs.Add(pool); | |||||
| } | |||||
| var h_pool = tf.concat(pooled_outputs, 3); | |||||
| var h_pool_flat = tf.reshape(h_pool, new TensorShape(-1, num_filters * filter_sizes.Rank)); | |||||
| Tensor h_drop = null; | |||||
| tf_with(tf.name_scope("dropout"), delegate | |||||
| { | |||||
| h_drop = tf.nn.dropout(h_pool_flat, keep_prob); | |||||
| }); | |||||
| Tensor logits = null; | |||||
| Tensor predictions = null; | |||||
| tf_with(tf.name_scope("output"), delegate | |||||
| { | |||||
| logits = tf.layers.dense(h_drop, num_class); | |||||
| predictions = tf.argmax(logits, -1, output_type: tf.int32); | |||||
| }); | |||||
| tf_with(tf.name_scope("loss"), delegate | |||||
| { | |||||
| var sscel = tf.nn.sparse_softmax_cross_entropy_with_logits(logits: logits, labels: y); | |||||
| var loss = tf.reduce_mean(sscel); | |||||
| var adam = tf.train.AdamOptimizer(learning_rate); | |||||
| var optimizer = adam.minimize(loss, global_step: global_step); | |||||
| }); | |||||
| tf_with(tf.name_scope("accuracy"), delegate | |||||
| { | |||||
| var correct_predictions = tf.equal(predictions, y); | |||||
| var accuracy = tf.reduce_mean(tf.cast(correct_predictions, TF_DataType.TF_FLOAT), name: "accuracy"); | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,20 +0,0 @@ | |||||
| using System; | |||||
| namespace TensorFlowNET.Examples.Utility | |||||
| { | |||||
| public static class ArrayShuffling | |||||
| { | |||||
| public static T[] Shuffle<T>(this Random rng, T[] array) | |||||
| { | |||||
| int n = array.Length; | |||||
| while (n > 1) | |||||
| { | |||||
| int k = rng.Next(n--); | |||||
| T temp = array[n]; | |||||
| array[n] = array[k]; | |||||
| array[k] = temp; | |||||
| } | |||||
| return array; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,105 +0,0 @@ | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using Tensorflow.Estimators; | |||||
| namespace TensorFlowNET.Examples.Utility | |||||
| { | |||||
| public class CoNLLDataset | |||||
| { | |||||
| static Dictionary<string, int> vocab_chars; | |||||
| static Dictionary<string, int> vocab_words; | |||||
| static Dictionary<string, int> vocab_tags; | |||||
| HyperParams _hp; | |||||
| string _path; | |||||
| public CoNLLDataset(string path, HyperParams hp) | |||||
| { | |||||
| if (vocab_chars == null) | |||||
| vocab_chars = load_vocab(hp.filepath_chars); | |||||
| if (vocab_words == null) | |||||
| vocab_words = load_vocab(hp.filepath_words); | |||||
| if (vocab_tags == null) | |||||
| vocab_tags = load_vocab(hp.filepath_tags); | |||||
| _path = path; | |||||
| } | |||||
| private (int[], int) processing_word(string word) | |||||
| { | |||||
| var char_ids = word.ToCharArray().Select(x => vocab_chars[x.ToString()]).ToArray(); | |||||
| // 1. preprocess word | |||||
| if (true) // lowercase | |||||
| word = word.ToLower(); | |||||
| if (false) // isdigit | |||||
| word = "$NUM$"; | |||||
| // 2. get id of word | |||||
| int id = vocab_words.GetValueOrDefault(word, vocab_words["$UNK$"]); | |||||
| return (char_ids, id); | |||||
| } | |||||
| private int processing_tag(string word) | |||||
| { | |||||
| // 1. preprocess word | |||||
| if (false) // lowercase | |||||
| word = word.ToLower(); | |||||
| if (false) // isdigit | |||||
| word = "$NUM$"; | |||||
| // 2. get id of word | |||||
| int id = vocab_tags.GetValueOrDefault(word, -1); | |||||
| return id; | |||||
| } | |||||
| private Dictionary<string, int> load_vocab(string filename) | |||||
| { | |||||
| var dict = new Dictionary<string, int>(); | |||||
| int i = 0; | |||||
| File.ReadAllLines(filename) | |||||
| .Select(x => dict[x] = i++) | |||||
| .Count(); | |||||
| return dict; | |||||
| } | |||||
| public IEnumerable<((int[], int)[], int[])> GetItems() | |||||
| { | |||||
| var lines = File.ReadAllLines(_path); | |||||
| int niter = 0; | |||||
| var words = new List<(int[], int)>(); | |||||
| var tags = new List<int>(); | |||||
| foreach (var l in lines) | |||||
| { | |||||
| string line = l.Trim(); | |||||
| if (string.IsNullOrEmpty(line) || line.StartsWith("-DOCSTART-")) | |||||
| { | |||||
| if (words.Count > 0) | |||||
| { | |||||
| niter++; | |||||
| yield return (words.ToArray(), tags.ToArray()); | |||||
| words.Clear(); | |||||
| tags.Clear(); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| var ls = line.Split(' '); | |||||
| // process word | |||||
| var word = processing_word(ls[0]); | |||||
| var tag = processing_tag(ls[1]); | |||||
| words.Add(word); | |||||
| tags.Add(tag); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,102 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using ICSharpCode.SharpZipLib.Core; | |||||
| using ICSharpCode.SharpZipLib.GZip; | |||||
| using ICSharpCode.SharpZipLib.Tar; | |||||
| using System; | |||||
| using System.IO; | |||||
| using System.IO.Compression; | |||||
| using System.Linq; | |||||
| using System.Threading; | |||||
| using System.Threading.Tasks; | |||||
| namespace TensorFlowNET.Examples.Utility | |||||
| { | |||||
| public class Compress | |||||
| { | |||||
| public static void ExtractGZip(string gzipFileName, string targetDir) | |||||
| { | |||||
| // Use a 4K buffer. Any larger is a waste. | |||||
| byte[] dataBuffer = new byte[4096]; | |||||
| using (System.IO.Stream fs = new FileStream(gzipFileName, FileMode.Open, FileAccess.Read)) | |||||
| { | |||||
| using (GZipInputStream gzipStream = new GZipInputStream(fs)) | |||||
| { | |||||
| // Change this to your needs | |||||
| string fnOut = Path.Combine(targetDir, Path.GetFileNameWithoutExtension(gzipFileName)); | |||||
| using (FileStream fsOut = File.Create(fnOut)) | |||||
| { | |||||
| StreamUtils.Copy(gzipStream, fsOut, dataBuffer); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| public static void UnZip(String gzArchiveName, String destFolder) | |||||
| { | |||||
| var flag = gzArchiveName.Split(Path.DirectorySeparatorChar).Last().Split('.').First() + ".bin"; | |||||
| if (File.Exists(Path.Combine(destFolder, flag))) return; | |||||
| Console.WriteLine($"Extracting."); | |||||
| var task = Task.Run(() => | |||||
| { | |||||
| ZipFile.ExtractToDirectory(gzArchiveName, destFolder); | |||||
| }); | |||||
| while (!task.IsCompleted) | |||||
| { | |||||
| Thread.Sleep(200); | |||||
| Console.Write("."); | |||||
| } | |||||
| File.Create(Path.Combine(destFolder, flag)); | |||||
| Console.WriteLine(""); | |||||
| Console.WriteLine("Extracting is completed."); | |||||
| } | |||||
| public static void ExtractTGZ(String gzArchiveName, String destFolder) | |||||
| { | |||||
| var flag = gzArchiveName.Split(Path.DirectorySeparatorChar).Last().Split('.').First() + ".bin"; | |||||
| if (File.Exists(Path.Combine(destFolder, flag))) return; | |||||
| Console.WriteLine($"Extracting."); | |||||
| var task = Task.Run(() => | |||||
| { | |||||
| using (var inStream = File.OpenRead(gzArchiveName)) | |||||
| { | |||||
| using (var gzipStream = new GZipInputStream(inStream)) | |||||
| { | |||||
| using (TarArchive tarArchive = TarArchive.CreateInputTarArchive(gzipStream)) | |||||
| tarArchive.ExtractContents(destFolder); | |||||
| } | |||||
| } | |||||
| }); | |||||
| while (!task.IsCompleted) | |||||
| { | |||||
| Thread.Sleep(200); | |||||
| Console.Write("."); | |||||
| } | |||||
| File.Create(Path.Combine(destFolder, flag)); | |||||
| Console.WriteLine(""); | |||||
| Console.WriteLine("Extracting is completed."); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,81 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using Newtonsoft.Json; | |||||
| using System.Collections.Generic; | |||||
| namespace TensorFlowNET.Examples.Utility | |||||
| { | |||||
| public class PbtxtItem | |||||
| { | |||||
| public string name { get; set; } | |||||
| public int id { get; set; } | |||||
| public string display_name { get; set; } | |||||
| } | |||||
| public class PbtxtItems | |||||
| { | |||||
| public List<PbtxtItem> items { get; set; } | |||||
| } | |||||
| public class PbtxtParser | |||||
| { | |||||
| public static PbtxtItems ParsePbtxtFile(string filePath) | |||||
| { | |||||
| string line; | |||||
| string newText = "{\"items\":["; | |||||
| using (System.IO.StreamReader reader = new System.IO.StreamReader(filePath)) | |||||
| { | |||||
| while ((line = reader.ReadLine()) != null) | |||||
| { | |||||
| string newline = string.Empty; | |||||
| if (line.Contains("{")) | |||||
| { | |||||
| newline = line.Replace("item", "").Trim(); | |||||
| //newText += line.Insert(line.IndexOf("=") + 1, "\"") + "\","; | |||||
| newText += newline; | |||||
| } | |||||
| else if (line.Contains("}")) | |||||
| { | |||||
| newText = newText.Remove(newText.Length - 1); | |||||
| newText += line; | |||||
| newText += ","; | |||||
| } | |||||
| else | |||||
| { | |||||
| newline = line.Replace(":", "\":").Trim(); | |||||
| newline = "\"" + newline;// newline.Insert(0, "\""); | |||||
| newline += ","; | |||||
| newText += newline; | |||||
| } | |||||
| } | |||||
| newText = newText.Remove(newText.Length - 1); | |||||
| newText += "]}"; | |||||
| reader.Close(); | |||||
| } | |||||
| PbtxtItems items = JsonConvert.DeserializeObject<PbtxtItems>(newText); | |||||
| return items; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,57 +0,0 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET 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. | |||||
| ******************************************************************************/ | |||||
| using System; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using System.Net; | |||||
| using System.Threading; | |||||
| using System.Threading.Tasks; | |||||
| namespace TensorFlowNET.Examples.Utility | |||||
| { | |||||
| public class Web | |||||
| { | |||||
| public static bool Download(string url, string destDir, string destFileName) | |||||
| { | |||||
| if (destFileName == null) | |||||
| destFileName = url.Split(Path.DirectorySeparatorChar).Last(); | |||||
| Directory.CreateDirectory(destDir); | |||||
| string relativeFilePath = Path.Combine(destDir, destFileName); | |||||
| if (File.Exists(relativeFilePath)) | |||||
| { | |||||
| Console.WriteLine($"{relativeFilePath} already exists."); | |||||
| return false; | |||||
| } | |||||
| var wc = new WebClient(); | |||||
| Console.WriteLine($"Downloading {relativeFilePath}"); | |||||
| var download = Task.Run(() => wc.DownloadFile(url, relativeFilePath)); | |||||
| while (!download.IsCompleted) | |||||
| { | |||||
| Thread.Sleep(1000); | |||||
| Console.Write("."); | |||||
| } | |||||
| Console.WriteLine(""); | |||||
| Console.WriteLine($"Downloaded {relativeFilePath}"); | |||||
| return true; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,115 +0,0 @@ | |||||
| | |||||
| from __future__ import absolute_import, division, print_function | |||||
| import tensorflow as tf | |||||
| from tensorflow import keras | |||||
| import numpy as np | |||||
| print(tf.__version__) | |||||
| imdb = keras.datasets.imdb | |||||
| (train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000) | |||||
| print("Training entries: {}, labels: {}".format(len(train_data), len(train_labels))) | |||||
| print(train_data[0]) | |||||
| len(train_data[0]), len(train_data[1]) | |||||
| # A dictionary mapping words to an integer index | |||||
| word_index = imdb.get_word_index() | |||||
| # The first indices are reserved | |||||
| word_index = {k:(v+3) for k,v in word_index.items()} | |||||
| word_index["<PAD>"] = 0 | |||||
| word_index["<START>"] = 1 | |||||
| word_index["<UNK>"] = 2 # unknown | |||||
| word_index["<UNUSED>"] = 3 | |||||
| reverse_word_index = dict([(value, key) for (key, value) in word_index.items()]) | |||||
| def decode_review(text): | |||||
| return ' '.join([reverse_word_index.get(i, '?') for i in text]) | |||||
| decode_review(train_data[0]) | |||||
| train_data = keras.preprocessing.sequence.pad_sequences(train_data, | |||||
| value=word_index["<PAD>"], | |||||
| padding='post', | |||||
| maxlen=256) | |||||
| test_data = keras.preprocessing.sequence.pad_sequences(test_data, | |||||
| value=word_index["<PAD>"], | |||||
| padding='post', | |||||
| maxlen=256) | |||||
| print(train_data[0]) | |||||
| # input shape is the vocabulary count used for the movie reviews (10,000 words) | |||||
| vocab_size = 10000 | |||||
| model = keras.Sequential() | |||||
| model.add(keras.layers.Embedding(vocab_size, 16)) | |||||
| model.add(keras.layers.GlobalAveragePooling1D()) | |||||
| model.add(keras.layers.Dense(16, activation=tf.nn.relu)) | |||||
| model.add(keras.layers.Dense(1, activation=tf.nn.sigmoid)) | |||||
| model.summary() | |||||
| model.compile(optimizer='adam', | |||||
| loss='binary_crossentropy', | |||||
| metrics=['accuracy']) | |||||
| x_val = train_data[:10000] | |||||
| partial_x_train = train_data[10000:] | |||||
| y_val = train_labels[:10000] | |||||
| partial_y_train = train_labels[10000:] | |||||
| history = model.fit(partial_x_train, | |||||
| partial_y_train, | |||||
| epochs=20, | |||||
| batch_size=512, | |||||
| validation_data=(x_val, y_val), | |||||
| verbose=1) | |||||
| results = model.evaluate(test_data, test_labels) | |||||
| print(results) | |||||
| history_dict = history.history | |||||
| history_dict.keys() | |||||
| import matplotlib.pyplot as plt | |||||
| acc = history_dict['acc'] | |||||
| val_acc = history_dict['val_acc'] | |||||
| loss = history_dict['loss'] | |||||
| val_loss = history_dict['val_loss'] | |||||
| epochs = range(1, len(acc) + 1) | |||||
| # "bo" is for "blue dot" | |||||
| plt.plot(epochs, loss, 'bo', label='Training loss') | |||||
| # b is for "solid blue line" | |||||
| plt.plot(epochs, val_loss, 'b', label='Validation loss') | |||||
| plt.title('Training and validation loss') | |||||
| plt.xlabel('Epochs') | |||||
| plt.ylabel('Loss') | |||||
| plt.legend() | |||||
| plt.show() | |||||
| plt.clf() # clear figure | |||||
| plt.plot(epochs, acc, 'bo', label='Training acc') | |||||
| plt.plot(epochs, val_acc, 'b', label='Validation acc') | |||||
| plt.title('Training and validation accuracy') | |||||
| plt.xlabel('Epochs') | |||||
| plt.ylabel('Accuracy') | |||||
| plt.legend() | |||||
| plt.show() | |||||
| @@ -1,107 +0,0 @@ | |||||
| ''' | |||||
| A linear regression learning algorithm example using TensorFlow library. | |||||
| Author: Aymeric Damien | |||||
| Project: https://github.com/aymericdamien/TensorFlow-Examples/ | |||||
| ''' | |||||
| from __future__ import print_function | |||||
| import tensorflow as tf | |||||
| import numpy | |||||
| import matplotlib.pyplot as plt | |||||
| rng = numpy.random | |||||
| # Parameters | |||||
| learning_rate = 0.01 | |||||
| training_epochs = 1000 | |||||
| display_step = 10 | |||||
| # Training Data | |||||
| train_X = numpy.asarray([3.3,4.4,5.5,6.71,6.93,4.168,9.779,6.182,7.59,2.167, | |||||
| 7.042,10.791,5.313,7.997,5.654,9.27,3.1]) | |||||
| train_Y = numpy.asarray([1.7,2.76,2.09,3.19,1.694,1.573,3.366,2.596,2.53,1.221, | |||||
| 2.827,3.465,1.65,2.904,2.42,2.94,1.3]) | |||||
| n_samples = train_X.shape[0] | |||||
| if False: | |||||
| # tf Graph Input | |||||
| X = tf.placeholder("float") | |||||
| Y = tf.placeholder("float") | |||||
| # Set model weights | |||||
| W = tf.Variable(-0.06, name="weight") | |||||
| b = tf.Variable(-0.73, name="bias") | |||||
| # Construct a linear model | |||||
| mul = tf.multiply(X, W) | |||||
| pred = tf.add(mul, b) | |||||
| # Mean squared error | |||||
| sub = pred-Y | |||||
| pow = tf.pow(sub, 2) | |||||
| reduce = tf.reduce_sum(pow) | |||||
| cost = reduce/(2*n_samples) | |||||
| # Gradient descent | |||||
| # Note, minimize() knows to modify W and b because Variable objects are trainable=True by default | |||||
| grad = tf.train.GradientDescentOptimizer(learning_rate) | |||||
| optimizer = grad.minimize(cost) | |||||
| # tf.train.export_meta_graph(filename='save_model.meta'); | |||||
| else: | |||||
| # tf Graph Input | |||||
| new_saver = tf.train.import_meta_graph("linear_regression.meta") | |||||
| nodes = tf.get_default_graph()._nodes_by_name; | |||||
| optimizer = nodes["GradientDescent"] | |||||
| cost = nodes["truediv"].outputs[0] | |||||
| X = nodes["Placeholder"].outputs[0] | |||||
| Y = nodes["Placeholder_1"].outputs[0] | |||||
| W = nodes["weight"].outputs[0] | |||||
| b = nodes["bias"].outputs[0] | |||||
| pred = nodes["Add"].outputs[0] | |||||
| # Initialize the variables (i.e. assign their default value) | |||||
| init = tf.global_variables_initializer() | |||||
| # Start training | |||||
| with tf.Session() as sess: | |||||
| # Run the initializer | |||||
| sess.run(init) | |||||
| # Fit all training data | |||||
| for epoch in range(training_epochs): | |||||
| for (x, y) in zip(train_X, train_Y): | |||||
| sess.run(optimizer, feed_dict={X: x, Y: y}) | |||||
| # Display logs per epoch step | |||||
| if (epoch+1) % display_step == 0: | |||||
| c = sess.run(cost, feed_dict={X: train_X, Y:train_Y}) | |||||
| print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(c), \ | |||||
| "W=", sess.run(W), "b=", sess.run(b)) | |||||
| print("Optimization Finished!") | |||||
| training_cost = sess.run(cost, feed_dict={X: train_X, Y: train_Y}) | |||||
| print("Training cost=", training_cost, "W=", sess.run(W), "b=", sess.run(b), '\n') | |||||
| # Graphic display | |||||
| plt.plot(train_X, train_Y, 'ro', label='Original data') | |||||
| plt.plot(train_X, sess.run(W) * train_X + sess.run(b), label='Fitted line') | |||||
| plt.legend() | |||||
| plt.show() | |||||
| # Testing example, as requested (Issue #2) | |||||
| test_X = numpy.asarray([6.83, 4.668, 8.9, 7.91, 5.7, 8.7, 3.1, 2.1]) | |||||
| test_Y = numpy.asarray([1.84, 2.273, 3.2, 2.831, 2.92, 3.24, 1.35, 1.03]) | |||||
| print("Testing... (Mean square loss Comparison)") | |||||
| testing_cost = sess.run( | |||||
| tf.reduce_sum(tf.pow(pred - Y, 2)) / (2 * test_X.shape[0]), | |||||
| feed_dict={X: test_X, Y: test_Y}) # same function as cost above | |||||
| print("Testing cost=", testing_cost) | |||||
| print("Absolute mean square loss difference:", abs( | |||||
| training_cost - testing_cost)) | |||||
| plt.plot(test_X, test_Y, 'bo', label='Testing data') | |||||
| plt.plot(train_X, sess.run(W) * train_X + sess.run(b), label='Fitted line') | |||||
| plt.legend() | |||||
| plt.show() | |||||
| @@ -1,100 +0,0 @@ | |||||
| ''' | |||||
| A logistic regression learning algorithm example using TensorFlow library. | |||||
| This example is using the MNIST database of handwritten digits | |||||
| (http://yann.lecun.com/exdb/mnist/) | |||||
| Author: Aymeric Damien | |||||
| Project: https://github.com/aymericdamien/TensorFlow-Examples/ | |||||
| ''' | |||||
| from __future__ import print_function | |||||
| import tensorflow as tf | |||||
| # Import MNIST data | |||||
| from tensorflow.examples.tutorials.mnist import input_data | |||||
| mnist = input_data.read_data_sets("/tmp/data/", one_hot=True) | |||||
| # Parameters | |||||
| learning_rate = 0.01 | |||||
| training_epochs = 10 | |||||
| batch_size = 100 | |||||
| display_step = 1 | |||||
| # tf Graph Input | |||||
| x = tf.placeholder(tf.float32, [None, 784]) # mnist data image of shape 28*28=784 | |||||
| y = tf.placeholder(tf.float32, [None, 10]) # 0-9 digits recognition => 10 classes | |||||
| # Set model weights | |||||
| W = tf.Variable(tf.zeros([784, 10])) | |||||
| b = tf.Variable(tf.zeros([10])) | |||||
| # Construct model | |||||
| pred = tf.nn.softmax(tf.matmul(x, W) + b) # Softmax | |||||
| # Minimize error using cross entropy | |||||
| cost = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred), reduction_indices=1)) | |||||
| # Gradient Descent | |||||
| optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost) | |||||
| # Initialize the variables (i.e. assign their default value) | |||||
| init = tf.global_variables_initializer() | |||||
| # Start training | |||||
| with tf.Session() as sess: | |||||
| # Run the initializer | |||||
| sess.run(init) | |||||
| # Training cycle | |||||
| for epoch in range(training_epochs): | |||||
| avg_cost = 0. | |||||
| total_batch = int(mnist.train.num_examples/batch_size) | |||||
| # Loop over all batches | |||||
| for i in range(total_batch): | |||||
| batch_xs, batch_ys = mnist.train.next_batch(batch_size) | |||||
| # Run optimization op (backprop) and cost op (to get loss value) | |||||
| _, c = sess.run([optimizer, cost], feed_dict={x: batch_xs, | |||||
| y: batch_ys}) | |||||
| # Compute average loss | |||||
| avg_cost += c / total_batch | |||||
| # Display logs per epoch step | |||||
| if (epoch+1) % display_step == 0: | |||||
| print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(avg_cost)) | |||||
| print("Optimization Finished!") | |||||
| # Test model | |||||
| correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1)) | |||||
| # Calculate accuracy | |||||
| accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) | |||||
| print("Accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels})) | |||||
| # predict | |||||
| # results = sess.run(pred, feed_dict={x: batch_xs[:1]}) | |||||
| # save model | |||||
| saver = tf.train.Saver() | |||||
| save_path = saver.save(sess, "logistic_regression/model.ckpt") | |||||
| tf.train.write_graph(sess.graph.as_graph_def(),'logistic_regression','model.pbtxt', as_text=True) | |||||
| freeze_graph.freeze_graph(input_graph = 'logistic_regression/model.pbtxt', | |||||
| input_saver = "", | |||||
| input_binary = False, | |||||
| input_checkpoint = 'logistic_regression/model.ckpt', | |||||
| output_node_names = "Softmax", | |||||
| restore_op_name = "save/restore_all", | |||||
| filename_tensor_name = "save/Const:0", | |||||
| output_graph = 'logistic_regression/model.pb', | |||||
| clear_devices = True, | |||||
| initializer_nodes = "") | |||||
| # restoring the model | |||||
| saver = tf.train.import_meta_graph('logistic_regression/tensorflowModel.ckpt.meta') | |||||
| saver.restore(sess,tf.train.latest_checkpoint('logistic_regression')) | |||||
| # predict | |||||
| # pred = graph._nodes_by_name["Softmax"] | |||||
| # output = pred.outputs[0] | |||||
| # x = graph._nodes_by_name["Placeholder"] | |||||
| # input = x.outputs[0] | |||||
| # results = sess.run(output, feed_dict={input: batch_xs[:1]}) | |||||
| @@ -1,67 +0,0 @@ | |||||
| | |||||
| import tensorflow as tf | |||||
| import math | |||||
| # Creates an inference graph. | |||||
| # Hidden 1 | |||||
| images = tf.constant(1.2, tf.float32, shape=[100, 28]) | |||||
| with tf.name_scope("hidden1"): | |||||
| weights = tf.Variable( | |||||
| tf.truncated_normal([28, 128], | |||||
| stddev=1.0 / math.sqrt(float(28))), | |||||
| name="weights") | |||||
| biases = tf.Variable(tf.zeros([128]), | |||||
| name="biases") | |||||
| hidden1 = tf.nn.relu(tf.matmul(images, weights) + biases) | |||||
| # Hidden 2 | |||||
| with tf.name_scope("hidden2"): | |||||
| weights = tf.Variable( | |||||
| tf.truncated_normal([128, 32], | |||||
| stddev=1.0 / math.sqrt(float(128))), | |||||
| name="weights") | |||||
| biases = tf.Variable(tf.zeros([32]), | |||||
| name="biases") | |||||
| hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases) | |||||
| # Linear | |||||
| with tf.name_scope("softmax_linear"): | |||||
| weights = tf.Variable( | |||||
| tf.truncated_normal([32, 10], | |||||
| stddev=1.0 / math.sqrt(float(32))), | |||||
| name="weights") | |||||
| biases = tf.Variable(tf.zeros([10]), | |||||
| name="biases") | |||||
| logits = tf.matmul(hidden2, weights) + biases | |||||
| tf.add_to_collection("logits", logits) | |||||
| init_all_op = tf.global_variables_initializer() | |||||
| with tf.Session() as sess: | |||||
| # Initializes all the variables. | |||||
| sess.run(init_all_op) | |||||
| # Runs to logit. | |||||
| sess.run(logits) | |||||
| # Creates a saver. | |||||
| saver0 = tf.train.Saver() | |||||
| saver0.save(sess, 'my-save-dir/my-model-10000') | |||||
| # Generates MetaGraphDef. | |||||
| saver0.export_meta_graph('my-save-dir/my-model-10000.meta') | |||||
| # Then later import it and extend it to a training graph. | |||||
| with tf.Session() as sess: | |||||
| new_saver = tf.train.import_meta_graph('my-save-dir/my-model-10000.meta') | |||||
| new_saver.restore(sess, 'my-save-dir/my-model-10000') | |||||
| # Addes loss and train. | |||||
| labels = tf.constant(0, tf.int32, shape=[100], name="labels") | |||||
| batch_size = tf.size(labels) | |||||
| logits = tf.get_collection("logits")[0] | |||||
| loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, | |||||
| logits=logits) | |||||
| tf.summary.scalar('loss', loss) | |||||
| # Creates the gradient descent optimizer with the given learning rate. | |||||
| optimizer = tf.train.GradientDescentOptimizer(0.01) | |||||
| # Runs train_op. | |||||
| train_op = optimizer.minimize(loss) | |||||
| sess.run(train_op) | |||||
| @@ -1,78 +0,0 @@ | |||||
| import tensorflow as tf | |||||
| from tensorflow.contrib import rnn | |||||
| #import mnist dataset | |||||
| from tensorflow.examples.tutorials.mnist import input_data | |||||
| mnist=input_data.read_data_sets("/tmp/data/",one_hot=True) | |||||
| #define constants | |||||
| #unrolled through 28 time steps | |||||
| time_steps=28 | |||||
| #hidden LSTM units | |||||
| num_units=128 | |||||
| #rows of 28 pixels | |||||
| n_input=28 | |||||
| #learning rate for adam | |||||
| learning_rate=0.001 | |||||
| #mnist is meant to be classified in 10 classes(0-9). | |||||
| n_classes=10 | |||||
| #size of batch | |||||
| batch_size=128 | |||||
| #weights and biases of appropriate shape to accomplish above task | |||||
| out_weights=tf.Variable(tf.random_normal([num_units,n_classes])) | |||||
| out_bias=tf.Variable(tf.random_normal([n_classes])) | |||||
| #defining placeholders | |||||
| #input image placeholder | |||||
| x=tf.placeholder("float",[None,time_steps,n_input]) | |||||
| #input label placeholder | |||||
| y=tf.placeholder("float",[None,n_classes]) | |||||
| #processing the input tensor from [batch_size,n_steps,n_input] to "time_steps" number of [batch_size,n_input] tensors | |||||
| input=tf.unstack(x ,time_steps,1) | |||||
| #defining the network | |||||
| lstm_layer=rnn.BasicLSTMCell(num_units,forget_bias=1) | |||||
| outputs,_=rnn.static_rnn(lstm_layer,input,dtype="float32") | |||||
| #converting last output of dimension [batch_size,num_units] to [batch_size,n_classes] by out_weight multiplication | |||||
| prediction=tf.matmul(outputs[-1],out_weights)+out_bias | |||||
| #loss_function | |||||
| loss=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=prediction,labels=y)) | |||||
| #optimization | |||||
| opt=tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss) | |||||
| #model evaluation | |||||
| correct_prediction=tf.equal(tf.argmax(prediction,1),tf.argmax(y,1)) | |||||
| accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) | |||||
| #initialize variables | |||||
| init=tf.global_variables_initializer() | |||||
| with tf.Session() as sess: | |||||
| sess.run(init) | |||||
| iter=1 | |||||
| while iter<800: | |||||
| batch_x,batch_y=mnist.train.next_batch(batch_size=batch_size) | |||||
| batch_x=batch_x.reshape((batch_size,time_steps,n_input)) | |||||
| sess.run(opt, feed_dict={x: batch_x, y: batch_y}) | |||||
| if iter %10==0: | |||||
| acc=sess.run(accuracy,feed_dict={x:batch_x,y:batch_y}) | |||||
| los=sess.run(loss,feed_dict={x:batch_x,y:batch_y}) | |||||
| print("For iter ",iter) | |||||
| print("Accuracy ",acc) | |||||
| print("Loss ",los) | |||||
| print("__________________") | |||||
| iter=iter+1 | |||||
| #calculating test accuracy | |||||
| test_data = mnist.test.images[:128].reshape((-1, time_steps, n_input)) | |||||
| test_label = mnist.test.labels[:128] | |||||
| print("Testing Accuracy:", sess.run(accuracy, feed_dict={x: test_data, y: test_label})) | |||||
| @@ -1,48 +0,0 @@ | |||||
| import tensorflow as tf | |||||
| # hyperparameters | |||||
| n_neurons = 128 | |||||
| learning_rate = 0.001 | |||||
| batch_size = 128 | |||||
| n_epochs = 10 | |||||
| # parameters | |||||
| n_steps = 28 # 28 rows | |||||
| n_inputs = 28 # 28 cols | |||||
| n_outputs = 10 # 10 classes | |||||
| # build a rnn model | |||||
| X = tf.placeholder(tf.float32, [None, n_steps, n_inputs]) | |||||
| y = tf.placeholder(tf.int32, [None]) | |||||
| cell = tf.nn.rnn_cell.BasicRNNCell(num_units=n_neurons) | |||||
| output, state = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32) | |||||
| logits = tf.layers.dense(state, n_outputs) | |||||
| cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits) | |||||
| loss = tf.reduce_mean(cross_entropy) | |||||
| optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss) | |||||
| prediction = tf.nn.in_top_k(logits, y, 1) | |||||
| accuracy = tf.reduce_mean(tf.cast(prediction, tf.float32)) | |||||
| # input data | |||||
| from tensorflow.examples.tutorials.mnist import input_data | |||||
| mnist = input_data.read_data_sets("MNIST_data/") | |||||
| X_test = mnist.test.images # X_test shape: [num_test, 28*28] | |||||
| X_test = X_test.reshape([-1, n_steps, n_inputs]) | |||||
| y_test = mnist.test.labels | |||||
| # initialize the variables | |||||
| init = tf.global_variables_initializer() | |||||
| # train the model | |||||
| with tf.Session() as sess: | |||||
| sess.run(init) | |||||
| n_batches = mnist.train.num_examples // batch_size | |||||
| for epoch in range(n_epochs): | |||||
| for batch in range(n_batches): | |||||
| X_train, y_train = mnist.train.next_batch(batch_size) | |||||
| X_train = X_train.reshape([-1, n_steps, n_inputs]) | |||||
| sess.run(optimizer, feed_dict={X: X_train, y: y_train}) | |||||
| loss_train, acc_train = sess.run( | |||||
| [loss, accuracy], feed_dict={X: X_train, y: y_train}) | |||||
| print('Epoch: {}, Train Loss: {:.3f}, Train Acc: {:.3f}'.format( | |||||
| epoch + 1, loss_train, acc_train)) | |||||
| loss_test, acc_test = sess.run( | |||||
| [loss, accuracy], feed_dict={X: X_test, y: y_test}) | |||||
| print('Test Loss: {:.3f}, Test Acc: {:.3f}'.format(loss_test, acc_test)) | |||||
| @@ -1,164 +0,0 @@ | |||||
| # imports | |||||
| import tensorflow as tf | |||||
| import numpy as np | |||||
| import matplotlib.pyplot as plt | |||||
| img_h = img_w = 28 # MNIST images are 28x28 | |||||
| img_size_flat = img_h * img_w # 28x28=784, the total number of pixels | |||||
| n_classes = 10 # Number of classes, one class per digit | |||||
| def load_data(mode='train'): | |||||
| """ | |||||
| Function to (download and) load the MNIST data | |||||
| :param mode: train or test | |||||
| :return: images and the corresponding labels | |||||
| """ | |||||
| from tensorflow.examples.tutorials.mnist import input_data | |||||
| mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) | |||||
| if mode == 'train': | |||||
| x_train, y_train, x_valid, y_valid = mnist.train.images, mnist.train.labels, \ | |||||
| mnist.validation.images, mnist.validation.labels | |||||
| return x_train, y_train, x_valid, y_valid | |||||
| elif mode == 'test': | |||||
| x_test, y_test = mnist.test.images, mnist.test.labels | |||||
| return x_test, y_test | |||||
| def randomize(x, y): | |||||
| """ Randomizes the order of data samples and their corresponding labels""" | |||||
| permutation = np.random.permutation(y.shape[0]) | |||||
| shuffled_x = x[permutation, :] | |||||
| shuffled_y = y[permutation] | |||||
| return shuffled_x, shuffled_y | |||||
| def get_next_batch(x, y, start, end): | |||||
| x_batch = x[start:end] | |||||
| y_batch = y[start:end] | |||||
| return x_batch, y_batch | |||||
| # Load MNIST data | |||||
| x_train, y_train, x_valid, y_valid = load_data(mode='train') | |||||
| print("Size of:") | |||||
| print("- Training-set:\t\t{}".format(len(y_train))) | |||||
| print("- Validation-set:\t{}".format(len(y_valid))) | |||||
| print('x_train:\t{}'.format(x_train.shape)) | |||||
| print('y_train:\t{}'.format(y_train.shape)) | |||||
| print('x_train:\t{}'.format(x_valid.shape)) | |||||
| print('y_valid:\t{}'.format(y_valid.shape)) | |||||
| print(y_valid[:5, :]) | |||||
| # Hyper-parameters | |||||
| epochs = 10 # Total number of training epochs | |||||
| batch_size = 100 # Training batch size | |||||
| display_freq = 100 # Frequency of displaying the training results | |||||
| learning_rate = 0.001 # The optimization initial learning rate | |||||
| h1 = 200 # number of nodes in the 1st hidden layer | |||||
| # weight and bais wrappers | |||||
| def weight_variable(name, shape): | |||||
| """ | |||||
| Create a weight variable with appropriate initialization | |||||
| :param name: weight name | |||||
| :param shape: weight shape | |||||
| :return: initialized weight variable | |||||
| """ | |||||
| initer = tf.truncated_normal_initializer(stddev=0.01) | |||||
| return tf.get_variable('W_' + name, | |||||
| dtype=tf.float32, | |||||
| shape=shape, | |||||
| initializer=initer) | |||||
| def bias_variable(name, shape): | |||||
| """ | |||||
| Create a bias variable with appropriate initialization | |||||
| :param name: bias variable name | |||||
| :param shape: bias variable shape | |||||
| :return: initialized bias variable | |||||
| """ | |||||
| initial = tf.constant(0., shape=shape, dtype=tf.float32) | |||||
| return tf.get_variable('b_' + name, | |||||
| dtype=tf.float32, | |||||
| initializer=initial) | |||||
| def fc_layer(x, num_units, name, use_relu=True): | |||||
| """ | |||||
| Create a fully-connected layer | |||||
| :param x: input from previous layer | |||||
| :param num_units: number of hidden units in the fully-connected layer | |||||
| :param name: layer name | |||||
| :param use_relu: boolean to add ReLU non-linearity (or not) | |||||
| :return: The output array | |||||
| """ | |||||
| in_dim = x.get_shape()[1] | |||||
| W = weight_variable(name, shape=[in_dim, num_units]) | |||||
| b = bias_variable(name, [num_units]) | |||||
| layer = tf.matmul(x, W) | |||||
| layer += b | |||||
| if use_relu: | |||||
| layer = tf.nn.relu(layer) | |||||
| return layer | |||||
| # Create the graph for the linear model | |||||
| # Placeholders for inputs (x) and outputs(y) | |||||
| x = tf.placeholder(tf.float32, shape=[None, img_size_flat], name='X') | |||||
| y = tf.placeholder(tf.float32, shape=[None, n_classes], name='Y') | |||||
| # Create a fully-connected layer with h1 nodes as hidden layer | |||||
| fc1 = fc_layer(x, h1, 'FC1', use_relu=True) | |||||
| # Create a fully-connected layer with n_classes nodes as output layer | |||||
| output_logits = fc_layer(fc1, n_classes, 'OUT', use_relu=False) | |||||
| # Define the loss function, optimizer, and accuracy | |||||
| logits = tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=output_logits) | |||||
| loss = tf.reduce_mean(logits, name='loss') | |||||
| optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate, name='Adam-op').minimize(loss) | |||||
| correct_prediction = tf.equal(tf.argmax(output_logits, 1), tf.argmax(y, 1), name='correct_pred') | |||||
| accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name='accuracy') | |||||
| # Network predictions | |||||
| cls_prediction = tf.argmax(output_logits, axis=1, name='predictions') | |||||
| # export graph | |||||
| #tf.train.export_meta_graph(filename='neural_network.meta', graph=tf.get_default_graph(), clear_extraneous_savers= True, as_text = True) | |||||
| # Create the op for initializing all variables | |||||
| init = tf.global_variables_initializer() | |||||
| # Create an interactive session (to keep the session in the other cells) | |||||
| sess = tf.InteractiveSession() | |||||
| # Initialize all variables | |||||
| sess.run(init) | |||||
| # Number of training iterations in each epoch | |||||
| num_tr_iter = int(len(y_train) / batch_size) | |||||
| for epoch in range(epochs): | |||||
| print('Training epoch: {}'.format(epoch + 1)) | |||||
| # Randomly shuffle the training data at the beginning of each epoch | |||||
| x_train, y_train = randomize(x_train, y_train) | |||||
| for iteration in range(num_tr_iter): | |||||
| start = iteration * batch_size | |||||
| end = (iteration + 1) * batch_size | |||||
| x_batch, y_batch = get_next_batch(x_train, y_train, start, end) | |||||
| # Run optimization op (backprop) | |||||
| feed_dict_batch = {x: x_batch, y: y_batch} | |||||
| sess.run(optimizer, feed_dict=feed_dict_batch) | |||||
| if iteration % display_freq == 0: | |||||
| # Calculate and display the batch loss and accuracy | |||||
| loss_batch, acc_batch = sess.run([loss, accuracy], | |||||
| feed_dict=feed_dict_batch) | |||||
| print("iter {0:3d}:\t Loss={1:.2f},\tTraining Accuracy={2:.01%}". | |||||
| format(iteration, loss_batch, acc_batch)) | |||||
| # Run validation after every epoch | |||||
| feed_dict_valid = {x: x_valid[:1000], y: y_valid[:1000]} | |||||
| loss_valid, acc_valid = sess.run([loss, accuracy], feed_dict=feed_dict_valid) | |||||
| print('---------------------------------------------------------') | |||||
| print("Epoch: {0}, validation loss: {1:.2f}, validation accuracy: {2:.01%}". | |||||
| format(epoch + 1, loss_valid, acc_valid)) | |||||
| print('---------------------------------------------------------') | |||||
| @@ -1,126 +0,0 @@ | |||||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | |||||
| using Tensorflow; | |||||
| using TensorFlowNET.Examples; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.ExamplesTests | |||||
| { | |||||
| [TestClass] | |||||
| public class ExamplesTest | |||||
| { | |||||
| [TestMethod] | |||||
| public void BasicOperations() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| new BasicOperations() { Enabled = true }.Run(); | |||||
| } | |||||
| [TestMethod] | |||||
| public void HelloWorld() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| new HelloWorld() { Enabled = true }.Run(); | |||||
| } | |||||
| [TestMethod] | |||||
| public void ImageRecognition() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| new HelloWorld() { Enabled = true }.Run(); | |||||
| } | |||||
| [Ignore] | |||||
| [TestMethod] | |||||
| public void InceptionArchGoogLeNet() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| new InceptionArchGoogLeNet() { Enabled = true }.Run(); | |||||
| } | |||||
| [Ignore] | |||||
| [TestMethod] | |||||
| public void KMeansClustering() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| new KMeansClustering() { Enabled = true, IsImportingGraph = true, train_size = 500, validation_size = 100, test_size = 100, batch_size =100 }.Run(); | |||||
| } | |||||
| [TestMethod] | |||||
| public void LinearRegression() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| new LinearRegression() { Enabled = true }.Run(); | |||||
| } | |||||
| [TestMethod] | |||||
| public void LogisticRegression() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| new LogisticRegression() { Enabled = true, training_epochs=10, train_size = 500, validation_size = 100, test_size = 100 }.Run(); | |||||
| } | |||||
| [Ignore] | |||||
| [TestMethod] | |||||
| public void NaiveBayesClassifier() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| new NaiveBayesClassifier() { Enabled = false }.Run(); | |||||
| } | |||||
| [Ignore] | |||||
| [TestMethod] | |||||
| public void NamedEntityRecognition() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| new NamedEntityRecognition() { Enabled = true }.Run(); | |||||
| } | |||||
| [TestMethod] | |||||
| public void NearestNeighbor() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| new NearestNeighbor() { Enabled = true, TrainSize = 500, ValidationSize = 100, TestSize = 100 }.Run(); | |||||
| } | |||||
| [Ignore] | |||||
| [TestMethod] | |||||
| public void WordCnnTextClassification() | |||||
| => new CnnTextClassification { Enabled = true, ModelName = "word_cnn", DataLimit =100 }.Run(); | |||||
| [Ignore] | |||||
| [TestMethod] | |||||
| public void CharCnnTextClassification() | |||||
| => new CnnTextClassification { Enabled = true, ModelName = "char_cnn", DataLimit = 100 }.Run(); | |||||
| [Ignore] | |||||
| [TestMethod] | |||||
| public void TextClassificationWithMovieReviews() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| new BinaryTextClassification() { Enabled = true }.Run(); | |||||
| } | |||||
| [TestMethod] | |||||
| public void NeuralNetXor() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| Assert.IsTrue(new NeuralNetXor() { Enabled = true, IsImportingGraph = false }.Run()); | |||||
| } | |||||
| [Ignore("Not working")] | |||||
| [TestMethod] | |||||
| public void NeuralNetXor_ImportedGraph() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| Assert.IsTrue(new NeuralNetXor() { Enabled = true, IsImportingGraph = true }.Run()); | |||||
| } | |||||
| [Ignore("Not working")] | |||||
| [TestMethod] | |||||
| public void ObjectDetection() | |||||
| { | |||||
| tf.Graph().as_default(); | |||||
| Assert.IsTrue(new ObjectDetection() { Enabled = true, IsImportingGraph = true }.Run()); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -39,7 +39,6 @@ | |||||
| <ProjectReference Include="..\..\src\TensorFlowHub\TensorFlowHub.csproj" /> | <ProjectReference Include="..\..\src\TensorFlowHub\TensorFlowHub.csproj" /> | ||||
| <ProjectReference Include="..\..\src\TensorFlowNET.Core\TensorFlowNET.Core.csproj" /> | <ProjectReference Include="..\..\src\TensorFlowNET.Core\TensorFlowNET.Core.csproj" /> | ||||
| <ProjectReference Include="..\..\src\TensorFlowText\TensorFlowText.csproj" /> | <ProjectReference Include="..\..\src\TensorFlowText\TensorFlowText.csproj" /> | ||||
| <ProjectReference Include="..\TensorFlowNET.Examples\TensorFlowNET.Examples.csproj" /> | |||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||