<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Haiping Chen on Medium]]></title>
        <description><![CDATA[Stories by Haiping Chen on Medium]]></description>
        <link>https://medium.com/@haiping008?source=rss-898fc824568e------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*3fc7L5LlYrMwVC2WLdK9NQ@2x.jpeg</url>
            <title>Stories by Haiping Chen on Medium</title>
            <link>https://medium.com/@haiping008?source=rss-898fc824568e------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 19:42:26 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@haiping008/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Building AI Agent in Llama 2 and .NET 6]]></title>
            <link>https://medium.com/scisharp/building-ai-agent-in-llama-2-and-net-6-baf6b5c3f825?source=rss-898fc824568e------2</link>
            <guid isPermaLink="false">https://medium.com/p/baf6b5c3f825</guid>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[chatgpt]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[chatbots]]></category>
            <category><![CDATA[ai-agent]]></category>
            <dc:creator><![CDATA[Haiping Chen]]></dc:creator>
            <pubDate>Sun, 14 Jan 2024 19:48:55 GMT</pubDate>
            <atom:updated>2024-01-18T11:16:03.743Z</atom:updated>
            <content:encoded><![CDATA[<h3>Building AI Agent in Llama 2 and .NET 6</h3><p>An AI agent is a computer program or system that can perceive its environment, process information, and make decisions or take actions to achieve specific goals. AI agents are designed to mimic some aspects of human intelligence and behavior, allowing them to operate autonomously or semi-autonomously in their environment.</p><p>The connection between AI agents and LLMs lies in the way they interact. AI agents use LLMs as a reasoning engine to determine which actions to take and in which order to take them. Instead of using an LLM directly, you can use an agent and give it access to a set of tools to deliver a sequence based on your intended task. This approach enables intelligent cost-effective interactions between the agent and an LLM.</p><h3>How to build an AI Agent easily and quickly?</h3><p>I am now using some open source tools to build my own AI Agent, which involves two major open source projects: <a href="https://github.com/SciSharp/BotSharp-UI">BotSharp/ UI</a> and <a href="https://github.com/SciSharp/LLamaSharp">LLamaSharp</a>. I will introduce each step in detail in this blog and keep it updated. The steps introduced here are about a way to develop and run locally, so they will involve the operation of some configuration files and the explanation of some C# code. Because the environment used here is .NET, this technical blog is suitable as a reference for developers who already have a certain foundation in .NET/ C#. After the entire project is configured, you will probably see a running screenshot like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ya3PNXxAA1U3AwWw2MpQgw.png" /></figure><h3>Let’s start recording every step of the operations</h3><p>We use a business scenario demonstration officially provided by BotSharp, Pizza Restaurant, to show the specific configuration steps. First, we pull the source code from Github to local. This step requires cloning two open source projects.</p><pre>git clone https://github.com/SciSharp/BotSharp<br>cd BotSharp<br>dotnet run --project .\src\WebStarter<br><br>git clone https://github.com/SciSharp/BotSharp-UI<br>cd BotSharp-UI<br>npm install<br>npm run dev</pre><p>If there is no reference to <em>BotSharp.Plugin.LLamaSharp.csproj</em> in your local <em>WebStarter</em> project, please add the project reference manually. And add <em>BotSharp.Plugin.LLamaSharp</em> to <em>PluginLoader.Assemblies</em> in appsetting.json. Finally, you need to install the <em>LLamaSharp</em> backend package in <em>WebStarter</em>. You can choose to install the CPU version or the CUDA version. After both the front-end and back-end projects are started normally, you can visit <a href="http://localhost:5015/">http://localhost:5015/</a> to continue the operation. You can log in using the default administrator account. This account has been placed in the local configuration file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*15zVzdRqaoiLde-ToA_JUA.png" /></figure><p>The second step is to configure compatible <strong>llama 2</strong> model settings. You need to add an LLM Provider. Before doing this, you need to download the model file. The following is the reference code for LLM Provider configuration. You need to replace the configuration of <em>llama-sharp</em>.</p><pre>&quot;LlmProviders&quot;: [<br>  {<br>    &quot;Provider&quot;: &quot;azure-openai&quot;,<br>    &quot;Models&quot;: [<br>      {<br>        &quot;Name&quot;: &quot;gpt-35-turbo&quot;,<br>        &quot;ApiKey&quot;: &quot;&quot;,<br>        &quot;Endpoint&quot;: &quot;https://gpt-35-turbo-chat.openai.azure.com/&quot;,<br>        &quot;Type&quot;: &quot;chat&quot;,<br>        &quot;PromptCost&quot;: 0.0015,<br>        &quot;CompletionCost&quot;: 0.002<br>      },<br>      {<br>        &quot;Name&quot;: &quot;gpt-35-turbo-instruct&quot;,<br>        &quot;ApiKey&quot;: &quot;&quot;,<br>        &quot;Endpoint&quot;: &quot;https://gpt-35-turbo-text.openai.azure.com/&quot;,<br>        &quot;Type&quot;: &quot;text&quot;,<br>        &quot;PromptCost&quot;: 0.0015,<br>        &quot;CompletionCost&quot;: 0.002<br>      }<br>    ]<br>  },<br>  {<br>    &quot;Provider&quot;: &quot;llama-sharp&quot;,<br>    &quot;Models&quot;: [<br>      {<br>        &quot;Name&quot;: &quot;llama-2-7b-guanaco-qlora.Q2_K.gguf&quot;,<br>        &quot;Type&quot;: &quot;chat&quot;<br>      }<br>    ]<br>  }<br>]</pre><p>After modifying the appsettings.json file, you need to restart the BotSharp project for the update to take effect. Next, you can see the <em>LLamaSharp</em> plug-in in the Plugins interface. It is still in the Disabled status. Click Install to enable this plug-in. Regarding the operating principle of BotSharp plug-in, you can refer to the official documentation to learn more. In order to run the Pizza Restaurant example, you also need to install the <em>PizzaBot</em> plugin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*C5mF9FIxFQtwKflzz-qutw.png" /></figure><p>After installing these two plug-ins, click the menu Agents, and you will see that there are several more Agents here. These Agents are provided by the corresponding plug-ins. You can also make your own Agent plug-in to meet your business needs. Here we can see agents of <strong>Ordering</strong>, <strong>Order Inquiry</strong> and <strong>Payment</strong>. Different Agents will perform corresponding processing according to different requests from users.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1OiPio_EgDGTzTtWmhSTcw.png" /></figure><p>There is one last configuration left to support the <strong>Llama 2</strong> model. This configuration can be modified in Agent details. Update the <em>Model</em> of LLM Config’s <em>Provider</em> to your configuration. <em>Model</em> is the name of the model file you just downloaded.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6ETyBmxMM9THny79FJHcdA.png" /></figure><p>Okay, great work has been done. You can now test <strong>PizzaBot</strong>. Return to the Agents interface and click the <em>Chat Test</em> button under <strong>Ordering</strong> agent. If you are using <em>LLamaSharp’s</em> CPU Backend, you will encounter the problem of slow response speed. Switching to the GPU version will be much faster.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/861/1*zY1t1l4jNMozubbJEnw0lg.png" /></figure><p>OK, so far, you can use .NET to run an LLM Agent of the Llama model locally. <strong>BotSharp</strong> is an open source, extensible Agent design and management tool. If you are interested in learning more about this project, please go to <a href="https://github.com/SciSharp/BotSharp">Github</a> to save it and star it.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=baf6b5c3f825" width="1" height="1" alt=""><hr><p><a href="https://medium.com/scisharp/building-ai-agent-in-llama-2-and-net-6-baf6b5c3f825">Building AI Agent in Llama 2 and .NET 6</a> was originally published in <a href="https://medium.com/scisharp">SciSharp STACK</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Understand the LLM Agent Orchestration]]></title>
            <link>https://medium.com/scisharp/understand-the-llm-agent-orchestration-043ebfaead1f?source=rss-898fc824568e------2</link>
            <guid isPermaLink="false">https://medium.com/p/043ebfaead1f</guid>
            <category><![CDATA[chatbots]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[chatgpt]]></category>
            <category><![CDATA[llm]]></category>
            <dc:creator><![CDATA[Haiping Chen]]></dc:creator>
            <pubDate>Sun, 15 Oct 2023 22:43:25 GMT</pubDate>
            <atom:updated>2023-10-15T23:45:14.584Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>Explain in detail the components of Profile, Memory, Planning, and Action components.</blockquote><p>In the field of artificial intelligence, people’s expectations for Agents are growing day by day. Whenever a new open source tool or product based on Agent appears, it can trigger heated discussions, such as the previous <a href="https://github.com/Significant-Gravitas/AutoGPT">AutoGPT</a>. For those who are interested in Agent, I recommend a <a href="https://arxiv.org/pdf/2308.11432.pdf">paper</a>, which comprehensively introduces the architecture of Agent and is of great value for understanding the overall situation of Agent.</p><p>This paper explains in detail the concept, development history and recent research hotspots of Agent. In addition to these basic knowledge, I think the most valuable part is that it summarizes the architecture of Agent based on large language model (LLM), allowing us to design our own Agent according to a certain standard paradigm.</p><p>This article of mine mainly explains the construction strategy of Agent based on LLM from two key aspects: designing the Agent architecture to better utilize the capabilities of LLM, and how to give the Agent the ability to complete different tasks.</p><p>In terms of Agent architecture design, this paper proposes a unified framework, including Profile module, Memory module, Planning module and Action module.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*r3W3FQqof4JnuhPs" /></figure><h3>Profile module</h3><p>Define and manage the characteristics and behaviors of Agent roles. It contains a series of parameters and rules that describe various attributes of the Agent, such as roles, goals, abilities, knowledge, and behavior. These properties determine how the agent interacts with the environment, how it understands and responds to tasks, and how it makes decisions and plans. This module proposes three Agent role generation methods, including LLM generation method, data set alignment method and combination method.</p><p>1. LLM generation method: Use a large language model to automatically generate the personal characteristics of the agent, such as age, gender, personal preferences and other background information. The specific method is: first set the composition rules of agents and clarify the attributes that agents in the target population should have; then specify several manually created seed configuration files as examples; and finally use language models to generate a large number of agent configuration files. This approach can quickly generate configuration files in batches, but the resulting agents may lack detail due to the lack of precise control.</p><p>2. Data set alignment method: The agent’s profile information is obtained from real-world population data sets, such as by extracting population survey data and organizing it into a natural language description. This can make the agent behavior more realistic and credible and accurately reflect the attribute distribution of the real population. But it requires reliable large-scale data set support.</p><p>3. Combination method: Use real data sets to generate a part of key agents to ensure that they reflect the laws of the real world; then use the LLM generation method to supplement a large number of other agents to expand the number of agents. This not only ensures the authenticity of the agents, but also achieves a sufficient number of agents, allowing the system to simulate more complex social interactions. Careful configuration file design is the basis for building an effective proxy system.</p><h3><strong>Memory module</strong></h3><p>It plays an important role in the Agent system, which stores and organizes information obtained from the environment to guide future actions.</p><p>Structurally, a memory module usually contains two parts: short-term memory and long-term memory. Short-term memory temporarily stores recent perceptions, and long-term memory stores important information for retrieval at any time.</p><p>In terms of format, memory information can be expressed in natural language or encoded into vector embeddings to improve retrieval efficiency. You can also use database storage, or organize it into a structured list to represent memory semantics.</p><p>In operation, it mainly interacts with the environment through three mechanisms: memory reading, writing and reflection. Read and extract relevant information to guide actions, write and store important information, reflect and summarize insights to improve the level of abstraction.</p><h3>Planning module</h3><p>The main task is to help the Agent decompose complex tasks into more manageable sub-tasks and formulate effective strategies. It is roughly divided into two types, one is a plan that does not rely on feedback, and the other is a plan based on feedback.</p><p>Feedback-independent plans do not refer to post-task feedback during the formulation process and have several common strategies. For example, single-path reasoning generates plans step by step in a cascading manner. In addition, there is multi-path reasoning, which generates multiple alternative planning paths to form a tree or graph-like structure. Of course, we can also use an external planner to quickly search to find the optimal plan.</p><p>Feedback-based planning, which adjusts the plan based on feedback after task execution, is more suitable for situations where long-term planning is required. The source of feedback may come from objective feedback of task execution results, feedback based on human subjective judgment, or even feedback provided by an auxiliary model.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Xk6iD6PaARJiglal" /></figure><h3>Action module</h3><p>The responsibility is to transform abstract decisions into concrete actions. It is like a bridge that connects the Agent’s internal world and the external environment. When performing a task, consider the goal of the action, how it was generated, its scope of application, and its likely impact.</p><p>Ideally actions should be purposeful, such as completing a specific task, communicating with other agents, or exploring the environment. Actions can be generated by consulting past memory experiences or by following a preset plan. The scope of action can not only be expanded by leveraging external tools such as APIs and knowledge bases, but also requires leveraging the inherent capabilities of large language models (LLM), such as planning, dialogue, and understanding common sense.</p><p>The architecture is like the hardware of a PC, but relying solely on architectural design is not enough. We also need to give the Agent the ability to complete different tasks. These are regarded as “software” resources. Several methods are proposed in the paper, including model fine-tuning, prompt engineering, and mechanical engineering. Among them, prompt engineering is probably the most common form. The prompt word engineer we often hear is the role in this context.</p><p>The design and construction strategy of LLM-based Agent is a complex and challenging task. With the advancement of technology, I believe that more excellent AI applications will be produced through Agents in the future, and ordinary users can also create their own Agents through open source projects and become super individuals in the AI era. I hope everyone can take action as soon as possible, reserve more knowledge, and use or make their own Agent as soon as possible when the technology matures.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*in12uJ8MNAHHXeD9" /></figure><p>The design and construction strategy of LLM-based Agent is a complex and challenging task. With the advancement of technology, I believe that more excellent AI applications will be produced through Agents in the future, and ordinary users can also create their own Agents through open source projects and become super individuals in the AI era. For .NET developers, there are already some excellent frameworks to accelerate LLM system integration, such as <a href="https://github.com/microsoft/semantic-kernel">Semantic Kernel</a> and <a href="https://github.com/SciSharp/BotSharp">BotSharp</a>. I hope everyone can take action as soon as possible, reserve more knowledge, and use or make their own Agent as soon as possible when the technology matures.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=043ebfaead1f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/scisharp/understand-the-llm-agent-orchestration-043ebfaead1f">Understand the LLM Agent Orchestration</a> was originally published in <a href="https://medium.com/scisharp">SciSharp STACK</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Host a LLM Powered Chatbot in .NET]]></title>
            <link>https://haiping008.medium.com/host-a-llm-powered-chatbot-in-net-c6d68b28b8f1?source=rss-898fc824568e------2</link>
            <guid isPermaLink="false">https://medium.com/p/c6d68b28b8f1</guid>
            <category><![CDATA[chatbots]]></category>
            <category><![CDATA[langchain]]></category>
            <category><![CDATA[semantic-kernel]]></category>
            <category><![CDATA[llm]]></category>
            <dc:creator><![CDATA[Haiping Chen]]></dc:creator>
            <pubDate>Sun, 01 Oct 2023 02:32:01 GMT</pubDate>
            <atom:updated>2023-10-01T02:32:01.019Z</atom:updated>
            <content:encoded><![CDATA[<h3>Host a LLM Powered Chatbot in .NET</h3><p>2023 is the year when LLM begins to explode. Everyone is busy integrating LLM with their existing systems and making full use of LLM’s language and reasoning capabilities. With the help of LLM, chatbots show their true intelligence. There are currently several tools that can help developers integrate LLM, such as LangChain, LlamaIndex and EmbedChain, as well as Microsoft’s Semantic Kernel and AutoGen. These frameworks can accelerate LLM application development at a certain point.</p><p>I would like to introduce to you another LLM open source framework developed by .NET, <a href="https://github.com/SciSharp/BotSharp">BotSharp</a>. It is an enterprise-level LLM application construction framework written entirely in C# language. It can effectively accelerate the integration of enterprise business systems and LLM, and provides a comprehensive service from Agent. A complete set of code mechanisms from management to conversation management can truly be applied to production-level code quality, with the best programming paradigms and practices.</p><p>Let’s start with a simple introductory example to see how BotSharp connects traditional applications and LLM. This example is a pizza store’s AI customer service, which can help users create new pizza orders. Assume that you have been able to run the project and access the local Open API interface. The basic project setup code can be found <a href="https://botsharp.readthedocs.io/en/latest/quick-start/get-started.html">here</a>.</p><ol><li><strong>Create a Pizza Ordering Agent</strong></li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*en1SrVc4jfbpO-Rr3sroNA.png" /></figure><p>After creating the agent, you will see a new folder with the AgentId. Each file inside has a different purpose:</p><ul><li><strong><em>agent.json</em></strong><em> <br></em>This file contains basic information recorded for the agent.</li><li><strong><em>instruction.liquid</em></strong><em><br></em>This file contains a description of the agent’s capabilities, telling LLM your current role and business process. This prompt is defined using the <a href="https://shopify.dev/docs/api/liquid">liquid template</a>, and you can use the Hook function to dynamically set some variable values.</li><li><strong><em>functions.json<br></em></strong>This file is a function description of the agent. Functions are the only way for the Agent to interact with the outside world. The Agent can only access the outside world through function calls. They are defined using the <a href="https://json-schema.org/">JSON Schema</a> standard.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KgWDKYW7haMteSoT6Hg0zA.png" /></figure><p>Using files to define LLM’s Prompt and Function can be easily modified in subsequent expansions. The principle of separation of prompts and code is also implemented in the design.</p><p><strong>2. Now you can start your chatbot via command:</strong></p><pre>dotnet run --project .\src\WebStarter\WebStarter.csproj -p SolutionName=PizzaBot</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*g0Cl_d4O_3Ewhkq7WTCTiA.png" /></figure><p>Start a conversation with the BOT in Postman</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WvOj5iC_bf4FFsausxKRYA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Nhj-WCPRzvN6uYXjYzUcKA.png" /></figure><p>Did you notice that in the second conversation, LLM triggered a call to the function <em>get_pizza_types</em>. This function will correspond to the function in C# by name, and the specific function behavior can be defined and executed using C# code.</p><pre>public class GetPizzaTypesFn : IFunctionCallback<br>{<br>    public string Name =&gt; &quot;get_pizza_types&quot;;<br><br>    public async Task&lt;bool&gt; Execute(RoleDialogModel message)<br>    {<br>        message.ExecutionResult = &quot;Pepperoni Pizza, Cheese Pizza, Margherita Pizza&quot;;<br>        message.ExecutionData = new List&lt;string&gt;<br>        {<br>            &quot;Pepperoni Pizza&quot;,<br>            &quot;Cheese Pizza&quot;,<br>            &quot;Margherita Pizza&quot;<br>        };<br>        return true;<br>    }<br>}</pre><p>Let’s continue our conversation with Pizza Ordering:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9Em1lNZOgfuDxyJlhYbFRQ.png" /></figure><p>Bot will communicate with users based on the business process we defined in the previous instruction.liquid template. After the user confirms the quantity, the <em>get_pizza_price </em>function will be called to calculate the total order price.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CPbTlIyBsYuEFWz1CEG5RQ.png" /></figure><p>After the user confirms the order, the Bot will ask the user how to support the order. These processes are carried out completely in accordance with our process design. Meeting our business expectations.</p><p>From the above simple example, you can see that building LLM through BotSharp is very straightforward and simple. Scalability and code readability are very good. This simple example cannot demonstrate the power of BotSharp. In subsequent articles, I will introduce some of its more powerful functions to show how it can complete complex enterprise applications. The complete sample code can be found <a href="https://github.com/SciSharp/BotSharp/tree/master/tests/BotSharp.Plugin.PizzaBot">here</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c6d68b28b8f1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[C# Tensor: the absolute basics for beginners]]></title>
            <link>https://medium.com/scisharp/c-tensor-the-absolute-basics-for-beginners-d934bf773eba?source=rss-898fc824568e------2</link>
            <guid isPermaLink="false">https://medium.com/p/d934bf773eba</guid>
            <category><![CDATA[tensor]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Haiping Chen]]></dc:creator>
            <pubDate>Sat, 21 Jan 2023 18:44:51 GMT</pubDate>
            <atom:updated>2023-02-01T03:06:56.551Z</atom:updated>
            <content:encoded><![CDATA[<p>For developers who have been working on enterprise information system, the word <strong>Tensor </strong>may be very unfamiliar, and they have no idea what it means, and it may even sound strange. It is explained in Wiki as:</p><blockquote>In mathematics, a tensor is an algebraic object that describes a multilinear relationship between sets of algebraic objects related to a vector space. Tensors may map between different objects such as vectors, scalars, and even other tensors.</blockquote><p>Tensor can be represented in the form of multidimensional data, and each dimension can be used to represent a specific set of features. Let’s talk about how to use C# to do basic Tensor operations. .NET itself does not have a Tensor library, we need to use a third-party open source library to do Tensor operations.</p><pre>PM&gt; Install-Package TensorFlow.NET<br>PM&gt; Install-Package SciSharp.TensorFlow.Redist</pre><h3>How to create a Tensor?</h3><p>After installing the required libraries, we can start coding and operating Tensor. First, let’s create a 1-dimensional Tensor. This creation process is similar to initializing an array in C#. The only difference is that we need to use <strong>np.array</strong> to wrap the array. Tensor can be represented by a multidimensional array structure, so Tensor and NDArray are essentially the same thing. They can be converted to each other without performance loss, because the data blocks point to the same memory area.</p><pre>using static Tensorflow.Binding;<br>using Tensorflow.NumPy;<br><br>// Create an array in normal way<br>var a1 = new[] { 1, 2, 3, 4 };<br>// Wrap it as NDArray<br>NDArray nd1 = np.array(a1);<br>// Convert NDArray to Tensor<br>Tensor t1 = nd1;<br><br>// We can also initialize a Tensor from NDArray, <br>// That&#39;s because there is an implicity conversion.<br>// Tensor t1 = np.array(a1);</pre><p>Essentially, the operation on Tensor is the operation on NDArray. So in the following code snippets we can directly use <strong>NDArray</strong> instead of <strong>Tensor</strong> to do various operations in C#. The most commonly used operations on Tensor are data type conversion and dimension transformation, which can be easily done through the API provided in the <a href="https://github.com/SciSharp/TensorFlow.NET">TensorFlow Numpy</a> library. We can transform the nd1 array just now into a 2x2 two-dimensional array:</p><pre>var nd2 = nd1.reshape((2, 2));<br><br>// By looking at the data pointers of these two arrays, <br>// you can see that they point to the same data block. <br>// Therefore, the conversion of dimensions has almost no performance loss.<br>// nd1.buffer == nd2.buffer<br><br>// But for data type conversion, it is necessary to reallocate memory.<br>var nd3 = nd2.astype(np.float32);</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/253/1*k0z12tNYH0ozAL6SxVWIdA.png" /><figcaption>View through Visual Studio’s Debugger</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/229/1*XxOqyS5eZG4o2MHE-ewsBQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/278/1*cVb9HbUbXpF_UiXs8jf8eQ.png" /><figcaption>nd2 represented as 2 x 2 matrix</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/229/1*lci2hvxsLUnzaQbMv9N-mg.png" /><figcaption>As we can see nd1 and nd2 point to same memory blocks</figcaption></figure><p>For creational operations, we also have several commonly used initialization methods:</p><pre>// Allocate a 4 elements filled with zero.<br>var nd4 = np.zeros(4);<br><br>// Allocate a NDArray and filled with one.<br>var nd5 = np.ones(4);<br><br>// Allocate a 4 double data type of memory without default value.<br>var nd6 = np.empty(4);<br><br>// And even an array that contains a range of evenly spaced intervals.<br>var nd7 = np.arange(2, 9, 2);<br><br>// You can also use np.linspace() to create an array with values that are spaced linearly <br>// in a specified interval:<br>var nd8 = np.linspace(0, 10, num: 5);<br><br>// While the default data type is floating point (np.float64), <br>// you can explicitly specify which data type you want using the dtype keyword.<br>var nd9 = np.ones(2, dtype: np.int64);<br><br>// Return an array of ones with the same shape and type as a given array.<br>nd7 = nd7.reshape((2, 2));<br>var nd10 = np.ones_like(nd7);<br><br>// Return an array of zeros with the same shape and type as a given array.<br>nd10 = np.zeros_like(nd7);</pre><p>How do we know the Tensor’s shape and number of dimensions after the NDArray has been created or modified? There are 4 important properties in NDArray: <em>ndim</em>, <em>shape</em>, <em>size </em>and <em>dtype</em></p><p>ndim will tell you the number of axes, or dimensions, of the array.<br>size will tell you the total number of elements of the array. This is the <em>product</em> of the elements of the array’s shape.<br>shape will display a tuple of integers that indicate the number of elements stored along each dimension of the array. If, for example, you have a 2-D array with 2 rows and 3 columns, the shape of your array is (2, 3).<br>dtype will tell you the data type of the array.</p><pre>// shape is (2, 2)<br>print(nd2.shape);<br><br>// ndim is 2<br>print(nd2.ndim);<br><br>// dtype is int32<br>print(nd2.dtype);<br><br>// size is 4<br>print(nd2.size);</pre><h3>Concatenate, Sorting elements</h3><p>When you want to sort an existing array, you can use np.sort() to operate, which will return a new sorted array. You can use np.concatenate()to combine two different arrays.</p><pre>var arr = np.array(new[] { 2, 1, 5, 3, 7, 4, 6, 8 });<br>arr = np.sort(arr);<br><br>// adding more elements<br>var arr2 = np.array(new[] { 2, 3 });<br>var arr3 = np.concatenate((arr, arr2));</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/452/1*brKFlC9hxnUu_zohRBVvTQ.png" /></figure><p>The above content is about the most basic data creation of Tesnor. This article will continue to be updated and add more code explanations about Tensor operations.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d934bf773eba" width="1" height="1" alt=""><hr><p><a href="https://medium.com/scisharp/c-tensor-the-absolute-basics-for-beginners-d934bf773eba">C# Tensor: the absolute basics for beginners</a> was originally published in <a href="https://medium.com/scisharp">SciSharp STACK</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[TensorFlow AutoGraph for .NET]]></title>
            <link>https://medium.com/scisharp/tensorflow-autograph-for-net-a89f1e97a4a5?source=rss-898fc824568e------2</link>
            <guid isPermaLink="false">https://medium.com/p/a89f1e97a4a5</guid>
            <category><![CDATA[tensorflow]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[machinelerning]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Haiping Chen]]></dc:creator>
            <pubDate>Wed, 02 Dec 2020 01:48:10 GMT</pubDate>
            <atom:updated>2023-01-13T01:50:31.932Z</atom:updated>
            <content:encoded><![CDATA[<h3>AutoGraph for TensorFlow.NET</h3><p>TensorFlow 2.x has three mode of graph computation, namely static graph construction (the main method used by TensorFlow 1.x), Eager mode and AutoGraph method. In TensorFlow 2.x, the official recommendation is using the Eager mode and the AutoGraph method.</p><p>The Eager mode is convenient for model development and debugging by data scientist, the code is readable and the coding efficiency is high for the machine learning engineers, but the computation performance is not as good as the static computation graph. The execution efficiency of the static graph is very high, but the code writing and readability are poor, and the program debugging is difficult.</p><blockquote>In TensorFlow 2, eager execution is turned on by default. The user interface is intuitive and flexible (running one-off operations is much easier and faster), but this can come at the expense of performance and deployability.</blockquote><p>AutoGraph takes into account the two major advantages of dynamic graph coding efficiency and static graph execution efficiency. Literally understood, the AutoGraph mechanism is an automatic calculation graph conversion function, which can write codes developed in accordance with dynamic graph writing rules. , Through the AutoGraph mechanism, it is converted into a static computation graph and executed in the same way as a static calculation graph, achieving the purpose of “quickly writing code and debugging code in a dynamic graph” + “efficient code execution in a static graph”.</p><p>Of course, the code and usage scenarios that the AutoGraph mechanism can convert are not unconstrained (or it will completely replace the static calculation graph and the dynamic calculation graph). The fitness of the AutoGraph mechanism requires certain coding rules and a deep understanding of AutoGraph. Perform the internal operation process of the calculation graph conversion, otherwise the conversion will fail, or an abnormal execution process that does not meet the expectations will occur.</p><p>In the next two sections, we will explain in detail the principles and coding specifications of AutoGraph’s internal operating mechanism. Next, we will use a simple example to understand how to use the AutoGraph mechanism.</p><p>This is the simplest Tensor numeric multiplication operation:</p><pre>public void Run()<br>{<br>    var a = tf.constant(2);<br>    var b = tf.constant(3);<br>    var output = Mul(a, b);<br>    print(output);<br><br>    Console.ReadKey();<br>}</pre><pre>Tensor Mul(Tensor a, Tensor b)<br>{<br>    return a * b;<br>}</pre><p>After running, it will output the result of multiplying the values ​​2 * 3 = 6:</p><pre>tf.Tensor: shape=(), dtype=int32, numpy=6</pre><p>This process is carried out in dynamic computation graph mode, namely numerical computation in Eager Mode.</p><p>In <a href="https://github.com/SciSharp">TensorFlow for .NET</a>, we implement the AutoGraph mechanism in two ways:</p><p><strong>Method</strong> ① Manually run the <em>tf.autograph.to_graph()</em> method to convert the function into a static computation graph;</p><p><strong>Method</strong> ② Add Attribute property label <em>AutoGraph</em> before the function body to modify the function to realize automatic static graph conversion.</p><p>We recommend ways ② [AutoGraph] way, more flexible and convenient, the code more readable, let these two ways illustrate, respectively.</p><p><strong>① tf.autograph.to_graph() detailed description</strong></p><p>We can use the <em>tf.autograph.to_graph()</em> method to convert the dynamic calculation graph to a static calculation graph. The usage is very simple. It can be completed by adding a conversion code directly. Let’s perform the AutoGraph conversion test on the above multiplication operation.</p><p>Inject <em>tf.autograph.to_graph()</em> for AutoGraph conversion:</p><pre>public void Run()<br>{<br>    var func = tf.autograph.to_graph(Mul);// AutoGraph<br>    var a = tf.constant(2);<br>    var b = tf.constant(3);<br>    var output = func(a, b);<br>    print(output);<br><br>    Console.ReadKey();<br>}</pre><pre>Tensor Mul(Tensor a , Tensor b)<br>{<br>    return a * b;<br>}</pre><p>By adding a line of code <em>var func = tf.autograph.to_graph(Mul)</em>, we can realize the calculation graph conversion of the AutoGraph mechanism, and the result of the multiplication operation remains unchanged:</p><pre>tf.Tensor: shape=(), dtype=int32, numpy=6</pre><p>AutoGraph operating efficiency</p><p>Generally speaking, when the computational graph model is composed of a large number of small operations, the efficiency of <strong>AutoGraph</strong> is greatly improved. If the number of model operations is small, the efficiency of AutoGraph is not greatly improved, sometimes due to the time-consuming conversion of computational graphs , Resulting in longer running time.</p><p>Let’s make a simple modification to the previous example and add a loop test to test the running time under different conditions.</p><p><strong>Case 1#</strong> We directly increase the loop, and run the multiplication loop one million times</p><p>code show as below:</p><pre>public void Run()<br>{<br>    Stopwatch sw = new Stopwatch();<br>    sw.Restart();<br>    foreach (var item in range(1000000))<br>    {<br>        var a = tf.constant(2);<br>        var b = tf.constant(3);<br>        var output = Mul(a, b);<br>    }<br>    sw.Stop();<br>    print(&quot;Eager Mode：&quot; + sw.Elapsed.TotalSeconds.ToString(&quot;0.0 s&quot;));<br><br>    sw.Restart();<br>    var func = tf.autograph.to_graph(Mul);//AutoGraph<br>    foreach (var item in range(1000000))<br>    {<br>        var a = tf.constant(2);<br>        var b = tf.constant(3);<br>        var output = func(a, b);<br>    }<br>    sw.Stop();<br>    print(&quot;AutoGraph Mode：&quot; + sw.Elapsed.TotalSeconds.ToString(&quot;0.0 s&quot;));<br><br>    Console.ReadKey();<br>}</pre><pre>Tensor Mul(Tensor a, Tensor b)<br>{<br>    return a * b;<br>}</pre><p>The results are as follows:</p><pre>Eager Mode：20.2 s<br>AutoGraph Mode：41.8 s</pre><p>We can see that the Eager mode 20.2 s is faster than the AutoGraph mode 41.8 s (different PC configurations may have slightly different calculation results).</p><p><strong>Case 2#</strong> We add a little operand, and then run the multiplication operation in the same loop one million times</p><p>The operand of the multiplication operation has been added and modified to 4 consecutive multiplications <em>a * b * a * b * a * b * a * b</em>, the code is as follows:</p><pre>public void Run()<br>{<br>    Stopwatch sw = new Stopwatch();<br>    sw.Restart();<br>    foreach (var item in range(1000000))<br>    {<br>        var a = tf.constant(2);<br>        var b = tf.constant(3);<br>        var output = Mul(a, b);<br>    }<br>    sw.Stop();<br>    print(&quot;Eager Mode：&quot; + sw.Elapsed.TotalSeconds.ToString(&quot;0.0 s&quot;));<br><br>    sw.Restart();<br>    var func = tf.autograph.to_graph(Mul);//AutoGraph<br>    foreach (var item in range(1000000))<br>    {<br>        var a = tf.constant(2);<br>        var b = tf.constant(3);<br>        var output = func(a, b);<br>    }<br>    sw.Stop();<br>    print(&quot;AutoGraph Mode：&quot; + sw.Elapsed.TotalSeconds.ToString(&quot;0.0 s&quot;));<br><br>    Console.ReadKey();<br>}</pre><pre>Tensor Mul(Tensor a , Tensor b)<br>{<br>    return a * b * a * b * a * b * a * b;<br>}</pre><p>The results are as follows:</p><pre>Eager Mode：78.3 s<br>AutoGraph Mode：47.1 s</pre><p>This time, we can see that Eager mode 78.3 s is much slower than AutoGraph mode 47.1 s (different PC configurations may have slightly different calculation results), and the efficiency advantage of AutoGraph has been reflected.</p><p>Next, let’s look at other simple code examples of <strong>AutoGraph</strong>.</p><p>Example 1: Simple conditional comparison operation</p><p>A simple way to compare the size of 2 Tensor constant values ​​and output the smaller value:</p><pre>public  void  Run ()<br>{<br>    var func = tf.autograph.to_graph(Condition_Min);<br>    var a = tf.constant(3);<br>    var b = tf.constant(2);<br>    var output = func(a, b);<br>    print(output);<br><br>    Console.ReadKey();<br>}</pre><pre>// TwoInputs_OneOutput_Condition<br>Tensor Condition_Min(Tensor a, Tensor b)<br>{<br>    return tf.cond(a &lt; b, a, b);<br>}</pre><p>Run the code, the smaller value 2 is correctly output:</p><pre>tf.Tensor: shape=(), dtype=int32, numpy=2</pre><p>Example 2: <strong>AutoGraph</strong> conversion of <strong>Lambda</strong> expression</p><p>The AutoGraph mechanism also supports the conversion of static calculation graphs of Lambda expressions. A simple sample code is as follows:</p><pre>public  void  Run ()<br>{<br>    var func = tf.autograph.to_graph((x, y) =&gt; x * y);<br>    var output = func(tf.constant(3), tf.constant(2));<br>    print(output);<br><br>    Console.ReadKey();<br>}</pre><p>Running the code, the operation result of the Lambda multiplication expression is correctly output 6:</p><pre>tf.Tensor: shape=(), dtype=int32, numpy=6</pre><p><strong>② [AutoGraph] detailed description</strong></p><p>Another recommended AutoGraph conversion method is to add the Attribute property label <em>[AutoGraph]</em> in front of the function body to modify the function to realize automatic static graph conversion. This method is more convenient, the amount of code changes is less, and the program can be modified and more readable.</p><p>Let’s take a look through a few different examples.</p><p>Example 1# Floating point addition operation</p><p>This time we do an addition operation of floating-point decimals, the code is as follows:</p><pre>public  void  Run ()<br>{<br>    var a = tf.constant(2.0);<br>    var b = tf.constant(1.5);<br>    var output = Add(a, b);<br>    print(output);<br><br>    Console.ReadKey();<br>}</pre><pre>Tensor Add(Tensor a, Tensor b)<br>{<br>    var c = a + b;<br>    return c;<br>}</pre><p>After running, the program outputs the result of the addition operation:</p><pre>tf.Tensor: shape=(), dtype=TF_DOUBLE, numpy=3.5</pre><p>We can implement AutoGraph conversion by adding the feature tag <em>[AutoGraph]</em> in front of the <em>Add()</em> method. The code is as follows:</p><pre>public  void  Run ()<br>{<br>    var a = tf.constant(2.0);<br>    var b = tf.constant(1.5);<br>    var output = Add(a, b);<br>    print(output);</pre><pre>    Console.ReadKey();<br>}<br>[AutoGraph]<br>Tensor Add(Tensor a, Tensor b)<br>{<br>    var c = a + b;<br>    return c;<br>}</pre><p>After running, the program outputs the same result of the addition operation:</p><pre>tf.Tensor: shape=(), dtype=TF_DOUBLE, numpy=3.5</pre><p>Example 2# MNIST logistic regression test</p><p>Next, we will test a slightly more complicated case-MNIST logistic regression. For the specific content of MNIST logistic regression, you can refer to the example <a href="https://github.com/SciSharp/SciSharp-Stack-Examples">Handwritten Character Classification Logistic Regression</a>.</p><p>At the same time, we added a timer to test whether there is a difference in time between Eager mode and AutoGraph mode.</p><p>The complete console code of MNIST logistic regression in Eager mode is as follows:</p><pre>using static Tensorflow.KerasApi;<br>using Tensorflow;<br>using static Tensorflow.Binding;<br>using Tensorflow.Keras.Optimizers;<br>using System.Diagnostics;</pre><pre>namespace Test_Core<br>{<br>    class Program<br>    {<br>        static void Main(string[] args)<br>        {<br>            Stopwatch sw = new Stopwatch();<br>            sw.Restart();</pre><pre>            TFNET  tfnet  =  new  TFNET ();<br>            tfnet . Run ();</pre><pre>            sw.Stop();<br>            print(&quot;Time Last：&quot; + sw.Elapsed.TotalSeconds.ToString(&quot;0.0 s&quot;));<br>        }<br>    }</pre><pre>    class TFNET<br>    {<br>        ResourceVariable W = tf.Variable(tf.ones((784, 10)), name: &quot;weight&quot;);<br>        ResourceVariable b = tf.Variable(tf.zeros(10), name: &quot;bias&quot;);<br>        SGD optimizer = keras.optimizers.SGD(0.01f);<br>        public  void  Run ()<br>        {<br>            int training_epochs = 20000;<br>            int batch_size = 256;<br>            int num_features = 784; // 28*28<br>            int display_step = 1000;<br>            float accuracy = 0f;</pre><pre>            var ((x_train, y_train), (x_test, y_test)) = keras.datasets.mnist.load_data();<br>            (x_train, x_test) = (x_train.reshape((-1, num_features)), x_test.reshape((-1, num_features)));<br>            (x_train, x_test) = (x_train / 255f, x_test / 255f);</pre><pre>            var train_data = tf.data.Dataset.from_tensor_slices(x_train, y_train);<br>            train_data = train_data.repeat().shuffle(5000).batch(batch_size).prefetch(1);<br>            train_data = train_data.take(training_epochs);</pre><pre>            foreach (var (step, (batch_x, batch_y)) in enumerate(train_data, 1))<br>            {<br>                run_optimization(batch_x, batch_y);</pre><pre>                if (step % display_step == 0)<br>                {<br>                    var pred = logistic_regression(batch_x);<br>                    var loss = cross_entropy(pred, batch_y);<br>                    var acc = Accuracy(pred, batch_y);<br>                    print($&quot;step: {step}, loss: {(float)loss}, accuracy: {(float)acc}&quot;);<br>                    accuracy = acc.numpy();<br>                }<br>            }</pre><pre>            {<br>                var pred = logistic_regression(x_test);<br>                print($&quot;Test Accuracy: {(float)Accuracy(pred, y_test)}&quot;);<br>            }<br>        }<br>        Tensor Accuracy(Tensor y_pred, Tensor y_true)<br>        {<br>            var correct_prediction = tf.equal(tf.argmax(y_pred, 1), tf.cast(y_true, tf.int64));<br>            return tf.reduce_mean(tf.cast(correct_prediction, tf.float32));<br>        }<br>        Tensor cross_entropy(Tensor y_pred, Tensor y_true)<br>        {<br>            y_true = tf.cast(y_true, TF_DataType.TF_UINT8);<br>            y_true = tf.one_hot(y_true, depth: 10);<br>            y_pred = tf.clip_by_value(y_pred, 1e-9f, 1.0f);<br>            return tf.reduce_mean(-tf.reduce_sum(y_true * tf.math.log(y_pred), 1));<br>        }<br>        Tensor logistic_regression(Tensor x)<br>        {<br>            return tf.nn.softmax(tf.matmul(x, W) + b);<br>        }<br>        private void run_optimization(Tensor x, Tensor y)<br>        {<br>            using var g = tf.GradientTape();<br>            var pred = logistic_regression(x);<br>            var loss = cross_entropy(pred, y);<br>            var gradients = g.gradient(loss, (W, b));<br>            optimizer.apply_gradients(zip(gradients, (W, b)));<br>        }</pre><pre>    }<br>}</pre><p>The program execution took 47.2 seconds, and the running result output is as follows (different PCs may have slightly different execution time and calculation results):</p><pre>step: 1000, loss: 0.60991216, accuracy: 0.859375<br>step: 2000, loss: 0.52773017, accuracy: 0.8515625<br>step: 3000, loss: 0.49317402, accuracy: 0.86328125<br>step: 4000, loss: 0.3669852, accuracy: 0.8984375<br>step: 5000, loss: 0.34490967, accuracy: 0.91015625<br>step: 6000, loss: 0.36495364, accuracy: 0.90625<br>step: 7000, loss: 0.3448297, accuracy: 0.91796875<br>step: 8000, loss: 0.3595497, accuracy: 0.890625<br>step: 9000, loss: 0.4222083, accuracy: 0.87109375<br>step: 10000, loss: 0.3518588, accuracy: 0.90625<br>step: 11000, loss: 0.3254419, accuracy: 0.91015625<br>step: 12000, loss: 0.3375517, accuracy: 0.90234375<br>step: 13000, loss: 0.47696534, accuracy: 0.875<br>step: 14000, loss: 0.38535655, accuracy: 0.890625<br>step: 15000, loss: 0.4106849, accuracy: 0.875<br>step: 16000, loss: 0.33494166, accuracy: 0.90625<br>step: 17000, loss: 0.41341114, accuracy: 0.91796875<br>step: 18000, loss: 0.33995813, accuracy: 0.90625<br>step: 19000, loss: 0.32934952, accuracy: 0.9140625<br>Test Accuracy: 0.9166<br>Time Last：47.2 s</pre><p>We can implement AutoGraph conversion by adding the feature tag <em>[AutoGraph]</em> in front of the optimizer <em>run_optimization()</em> method. The complete console code is as follows:</p><pre>using static Tensorflow.KerasApi;<br>using Tensorflow;<br>using static Tensorflow.Binding;<br>using Tensorflow.Keras.Optimizers;<br>using System.Diagnostics;<br>using Tensorflow.Graphs;</pre><pre>namespace Test_Core<br>{<br>    class Program<br>    {<br>        static void Main(string[] args)<br>        {<br>            Stopwatch sw = new Stopwatch();<br>            sw.Restart();</pre><pre>            TFNET  tfnet  =  new  TFNET ();<br>            tfnet . Run ();</pre><pre>            sw.Stop();<br>            print(&quot;Time Last：&quot; + sw.Elapsed.TotalSeconds.ToString(&quot;0.0 s&quot;));<br>        }<br>    }</pre><pre>    class TFNET<br>    {<br>        ResourceVariable W = tf.Variable(tf.ones((784, 10)), name: &quot;weight&quot;);<br>        ResourceVariable b = tf.Variable(tf.zeros(10), name: &quot;bias&quot;);<br>        SGD optimizer = keras.optimizers.SGD(0.01f);<br>        public  void  Run ()<br>        {<br>            int training_epochs = 20000;<br>            int batch_size = 256;<br>            int num_features = 784; // 28*28<br>            int display_step = 1000;<br>            float accuracy = 0f;</pre><pre>            var ((x_train, y_train), (x_test, y_test)) = keras.datasets.mnist.load_data();<br>            (x_train, x_test) = (x_train.reshape((-1, num_features)), x_test.reshape((-1, num_features)));<br>            (x_train, x_test) = (x_train / 255f, x_test / 255f);</pre><pre>            var train_data = tf.data.Dataset.from_tensor_slices(x_train, y_train);<br>            train_data = train_data.repeat().shuffle(5000).batch(batch_size).prefetch(1);<br>            train_data = train_data.take(training_epochs);</pre><pre>            foreach (var (step, (batch_x, batch_y)) in enumerate(train_data, 1))<br>            {<br>                run_optimization(batch_x, batch_y);</pre><pre>                if (step % display_step == 0)<br>                {<br>                    var pred = logistic_regression(batch_x);<br>                    var loss = cross_entropy(pred, batch_y);<br>                    var acc = Accuracy(pred, batch_y);<br>                    print($&quot;step: {step}, loss: {(float)loss}, accuracy: {(float)acc}&quot;);<br>                    accuracy = acc.numpy();<br>                }<br>            }</pre><pre>            {<br>                var pred = logistic_regression(x_test);<br>                print($&quot;Test Accuracy: {(float)Accuracy(pred, y_test)}&quot;);<br>            }<br>        }<br>        Tensor Accuracy(Tensor y_pred, Tensor y_true)<br>        {<br>            var correct_prediction = tf.equal(tf.argmax(y_pred, 1), tf.cast(y_true, tf.int64));<br>            return tf.reduce_mean(tf.cast(correct_prediction, tf.float32));<br>        }<br>        Tensor cross_entropy(Tensor y_pred, Tensor y_true)<br>        {<br>            y_true = tf.cast(y_true, TF_DataType.TF_UINT8);<br>            y_true = tf.one_hot(y_true, depth: 10);<br>            y_pred = tf.clip_by_value(y_pred, 1e-9f, 1.0f);<br>            return tf.reduce_mean(-tf.reduce_sum(y_true * tf.math.log(y_pred), 1));<br>        }<br>        Tensor logistic_regression(Tensor x)<br>        {<br>            return tf.nn.softmax(tf.matmul(x, W) + b);<br>        }<br>        [AutoGraph]<br>        private void run_optimization(Tensor x, Tensor y)<br>        {<br>            using var g = tf.GradientTape();<br>            var pred = logistic_regression(x);<br>            var loss = cross_entropy(pred, y);<br>            var gradients = g.gradient(loss, (W, b));<br>            optimizer.apply_gradients(zip(gradients, (W, b)));<br>        }</pre><pre>    }<br>}</pre><p>This time the program execution took 45.3 seconds, and the running result output is as follows (different PCs may have slightly different execution time and calculation results):</p><pre>step: 1000, loss: 0.5845629, accuracy: 0.88671875<br>step: 2000, loss: 0.42607152, accuracy: 0.8984375<br>step: 3000, loss: 0.5029169, accuracy: 0.85546875<br>step: 4000, loss: 0.33637348, accuracy: 0.90625<br>step: 5000, loss: 0.4658397, accuracy: 0.875<br>step: 6000, loss: 0.3632791, accuracy: 0.89453125<br>step: 7000, loss: 0.38538253, accuracy: 0.90234375<br>step: 8000, loss: 0.3392726, accuracy: 0.90234375<br>step: 9000, loss: 0.30917627, accuracy: 0.90234375<br>step: 10000, loss: 0.3470266, accuracy: 0.9140625<br>step: 11000, loss: 0.33611432, accuracy: 0.921875<br>step: 12000, loss: 0.37535334, accuracy: 0.89453125<br>step: 13000, loss: 0.35773978, accuracy: 0.890625<br>step: 14000, loss: 0.35660252, accuracy: 0.8984375<br>step: 15000, loss: 0.23310906, accuracy: 0.9453125<br>step: 16000, loss: 0.3695503, accuracy: 0.88671875<br>step: 17000, loss: 0.31830546, accuracy: 0.90625<br>step: 18000, loss: 0.2850374, accuracy: 0.91796875<br>step: 19000, loss: 0.26065654, accuracy: 0.9375<br>Test Accuracy: 0.917<br>Time Last：45.3 s</pre><p>Comparing the results of the second time, after adding the AutoGraph mechanism, the program operation efficiency is not significantly improved, and the execution time is not much different.</p><p>Through the above two examples of “MNIST Logistic Regression Example” and “One Million Multiplication Operations”, we can see that for a single operation that is time-consuming, the performance improvement brought by the AutoGraph mechanism will not be much , And when the model consists of many small operations, the efficiency of the AutoGraph mechanism is greatly improved. In the actual application process, you can comprehensively consider specific application scenarios and selectively apply the AutoGraph mechanism.</p><h3>Principle of AutoGraph Mechanism</h3><p>When we use the <em>tf.autograph.to_graph()</em> or <em>[AutoGraph]</em> method to convert a function into a static calculation graph, what happens inside the program?</p><p>For example, we test the following code:</p><pre>public  void  Run ()<br>{<br>    var func = tf.autograph.to_graph(Add);//AutoGraph<br>    print(&quot;First Run:Initialization&quot;);</pre><pre>    var a = tf.constant(2);<br>    var b = tf.constant(3);<br>    var output = func(a, b);<br>    print($&quot;Second Run:{output.numpy()}&quot;);</pre><pre>    output = func(output, b);<br>    print($&quot;Third Run:{output.numpy()}&quot;);</pre><pre>    Console.ReadKey();<br>}</pre><pre>Tensor Add(Tensor a, Tensor b)<br>{<br>    foreach (var i in range(3))<br>        print(i);<br>    var c = a + b;<br>    print(c);<br>    print(&quot;tracing&quot;);</pre><pre>    return c;<br>}</pre><p>After running, we will see the following results:</p><pre>0<br>1<br>2<br>tf.Tensor &#39;add:0&#39; shape=&lt;unknown&gt; dtype=int32<br>tracing<br>First Run:Initialization<br>Second Run:5<br>Third Run:8</pre><p>Let’s analyze this process step by step. In general, two things have happened.</p><p>When we wrote the function body of <em>Add()</em>, nothing happened, only the signature of such a function was recorded in the C# memory stack.</p><p>When we call this function for the first time through the <em>tf.autograph.to_graph()</em> method, the first thing happens. The program creates a static calculation graph by analyzing the content of the <em>Add()</em> function body. The parsing process will track the code that executes the weight of the function, determine the Tensor type of each variable, and add the OP operator to the calculation graph according to the execution order to generate a fixed static calculation graph.</p><p>Therefore, we see that the terminal sequentially outputs the value of the loop variable <em>i = 0 1 2</em>, the initial content of the Tensor add operator c inside the function, and the print test string tracing at the end of the function body. Here we can also see from the content of the tensor c inside the function body that c is just an operation operator in the static calculation graph, and the initial calculation result 0 is not obtained according to the Eager mode.</p><p>When we call the function for the second time and pass in the parameter Tensor to be calculated, the second thing happens. The program automatically calls the static calculation graph just created, passes in the Tensor to be calculated, executes the calculation graph, and outputs the calculated result. In this process, the program no longer runs the internal code of the function body, and directly calls the calculation graph created in the previous step for calculations, so the <em>print()</em> method of many tests inside the function body will not be executed again.</p><p>Therefore, the program only outputs the second result “Second Run: 5”.</p><p>This operation is no longer in the Eager mode method, but similar to the following statement executed in TensorFlow 1.x:</p><pre>using (var sess = tf.Session(tf.get_default_graph()))<br>{<br>    var result = sess.run(tf.constant(2),tf.constant(3));<br>}</pre><p>The process of calling the function for the third time is exactly the same as that for the second time. The program still calls the original calculation graph for repeated calculations and outputs the result “Third Run: 8”.</p><p>We can see that through the <strong>AutoGraph</strong> mechanism, the execution efficiency of repeated operations can be improved dramatically.</p><p>Here I simply demonstrate the process by way of diagrams, as shown in the following figure:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nlCbnVtCUm5fEmBO3HnwPg.png" /></figure><p><em>Thanks for the SciSharp STACK again, bring fancy Machine Learning technology to .NET community.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a89f1e97a4a5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/scisharp/tensorflow-autograph-for-net-a89f1e97a4a5">TensorFlow AutoGraph for .NET</a> was originally published in <a href="https://medium.com/scisharp">SciSharp STACK</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Queue in TensorFlow .NET]]></title>
            <link>https://medium.com/scisharp/queue-in-tensorflow-net-6faef5e83b1?source=rss-898fc824568e------2</link>
            <guid isPermaLink="false">https://medium.com/p/6faef5e83b1</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[csharp]]></category>
            <category><![CDATA[dotnet]]></category>
            <dc:creator><![CDATA[Haiping Chen]]></dc:creator>
            <pubDate>Sat, 21 Sep 2019 15:57:21 GMT</pubDate>
            <atom:updated>2019-09-23T12:17:53.792Z</atom:updated>
            <content:encoded><![CDATA[<h3>Queue in TensorFlow .NET</h3><p>ThensorFlow is capable to handle multiple threads, and queues are powerful mechanism for asynchronous computation. If we have large datasets this can significantly speed up the training process of our models. This functionality is especially handy when reading, pre-processing and extracting in mini-batches our training data. The secret to being able to do professional and high performance training of our model is understanding TensorFlow queuing operations. TensorFlow has implemented 4 types of Queue: <strong>FIFOQueue</strong>, <strong>PaddingFIFOQueue</strong>, <strong>PriorityQueue</strong> and <strong>RandomShuffleQueue</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/992/1*ZvyM407UR-uCtUlzuV4Vog.jpeg" /></figure><p>Like everything in TensorFlow, a queue is a node in a computation graph. It’s a stateful node, like a variable: other nodes can modify its content, In particular, nodes can enqueue new items into the queue, or dequeue existing items from the queue.</p><p>To get started with queue, let’s consider a simple example. We will create a “first in, first out” queue (FIFOQueue) and fill it with numbers. Then we’ll construct a graph that takes an item off the queue, adds one to that item, and puts it back on the end of the queue.</p><pre>[TestMethod]<br><strong>public</strong> <strong>void</strong> FIFOQueue()<br>{<br>	<em>// create a first in first out queue with capacity up to 2</em><br>	<em>// and data type set as int32</em><br>	var queue = tf.FIFOQueue(2, tf.int32);<br>	<em>// init queue, push 2 elements into queue.</em><br>	var init = queue.enqueue_many(<strong>new</strong>[] { 10, 20 });<br>	<em>// pop out the first element</em><br>	var x = queue.dequeue();<br>	<em>// add 1</em><br>	var y = x + 1;<br>	<em>// push back into queue</em><br>	var inc = queue.enqueue(y);</pre><pre>	<strong>using</strong> (var sess = tf.Session())<br>	{<br>		<em>// init queue</em><br>		init.run();</pre><pre>		<em>// pop out first element and push back calculated y</em><br>		(int dequeued, _) = sess.run((x, inc));<br>		Assert.AreEqual(10, dequeued);</pre><pre>		(dequeued, _) = sess.run((x, inc));<br>		Assert.AreEqual(20, dequeued);</pre><pre>		(dequeued, _) = sess.run((x, inc));<br>		Assert.AreEqual(11, dequeued);</pre><pre>		(dequeued, _) = sess.run((x, inc));<br>		Assert.AreEqual(21, dequeued);<br>        <br>		<em>// thread will hang if you run sess.run(x) again</em><br>		<em>// until queue has more element.</em><br>	}<br>}</pre><p>Enqueue, EnqueueMany and Dequeue are special nodes. They take a pointer to the queue instead of a normal value, allowing them to change it. I first create a FIFOQueue <em>queue</em> of size up to 3, I enqueue two values into the <em>queue</em>. Then I immediately attempt to <em>dequeue</em> a value from it and assign it to <em>y</em> where I simply add 1 to the dequeued variable. Next, we start up a <em>session</em> and run. After we’ve run this operation a few times the queue will be empty - if we try and run the operation again, the main thread of the program will hang or block - this is because it will be waiting for another operation to be run to put more values in the queue.</p><h3>FIFOQueue</h3><p>Creates a queue that dequeues elements in a first-in first-out order. A FIFOQueue has bounded capacity; supports multiple concurrent producers and consumers; and provides exactly-once delivery. A FIFOQueue holds a list of up to capacity elements. Each element is a fixed-length tuple of tensors whose dtypes are described by dtypes, and whose shapes are optionally described by the shapes argument.</p><h3>PaddingFIFOQueue</h3><p>A FIFOQueue that supports batching variable-sized tensors by padding. A PaddingFIFOQueue may contain components with dynamic shape, while also supporting dequeue_many. A PaddingFIFOQueue holds a list of up to capacity elements. Each element is a fixed-length tuple of tensors whose dtypes are described by dtypes, and whose shapes are described by the shapes argument.</p><pre>[TestMethod]<br>public void PaddingFIFOQueue()<br>{<br>	var numbers = tf.placeholder(tf.int32);<br>	var queue = tf.PaddingFIFOQueue(10, tf.int32, new TensorShape(-1));<br>	var enqueue = queue.enqueue(numbers);<br>	var dequeue_many = queue.dequeue_many(n: 3);<br><br>	using(var sess = tf.Session())<br>	{<br>		sess.run(enqueue, (numbers, new[] { 1 }));<br>		sess.run(enqueue, (numbers, new[] { 2, 3 }));<br>		sess.run(enqueue, (numbers, new[] { 3, 4, 5 }));<br><br>		var result = sess.run(dequeue_many[0]);<br><br>		Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 1, 0, 0 }, result[0].ToArray&lt;int&gt;()));<br>		Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 2, 3, 0 }, result[1].ToArray&lt;int&gt;()));<br>		Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 3, 4, 5 }, result[2].ToArray&lt;int&gt;()));<br>	}<br>}</pre><h3>PriorityQueue</h3><p>A queue implementation that dequeues elements in prioritized order. A PriorityQueue has bounded capacity; supports multiple concurrent producers and consumers; and provides exactly-once delivery. A PriorityQueue holds a list of up to capacity elements. Each element is a fixed-length tuple of tensors whose dtypes are described by types, and whose shapes are optionally described by the shapes argument.</p><pre>[TestMethod]<br><strong>public</strong> <strong>void</strong> PriorityQueue()<br>{<br>	var queue = tf.PriorityQueue(3, tf.@string);<br>	var init = queue.enqueue_many(<strong>new</strong>[] { 2L, 4L, 3L }, <strong>new</strong>[] { &quot;p1&quot;, &quot;p2&quot;, &quot;p3&quot; });<br>	var x = queue.dequeue();<br><br>	<strong>using</strong> (var sess = tf.Session())<br>	{<br>		init.run();<br><br>		<em>// output will 2, 3, 4</em><br>		var result = sess.run(x);<br>		Assert.AreEqual(result[0].GetInt64(), 2L);<br><br>		result = sess.run(x);<br>		Assert.AreEqual(result[0].GetInt64(), 3L);<br><br>		result = sess.run(x);<br>		Assert.AreEqual(result[0].GetInt64(), 4L);<br>	}<br>}</pre><h3>RandomShuffleQueue</h3><p>A queue implementation that dequeues elements in a random order. A RandomShuffleQueue has bounded capacity; supports multiple concurrent producers and consumers; and provides exactly-once delivery. A RandomShuffleQueue holds a list of up to capacity elements. Each element is a fixed-length tuple of tensors whose dtypes are described by dtypes, and whose shapes are optionally described by the shapes argument.</p><pre>[TestMethod]<br><strong>public</strong> <strong>void</strong> RandomShuffleQueue()<br>{<br>	var queue = tf.RandomShuffleQueue(10, min_after_dequeue: 1, dtype: tf.int32);<br>	var init = queue.enqueue_many(<strong>new</strong>[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });<br>	var x = queue.dequeue();<br><br>	string results = &quot;&quot;;<br>	<strong>using</strong> (var sess = tf.Session())<br>	{<br>		init.run();<br><br>		<strong>foreach</strong>(var i <strong>in</strong> range(9))<br>			results += (int)sess.run(x) + &quot;.&quot;;<br><br>		<em>// output in random order</em><br>		<em>// 1.2.3.4.5.6.7.8.9.</em><br>	}<br>}</pre><p>Queue methods must run on the same device as the queue. FIFOQueue and RandomShuffleQueue are important TensorFlow objects for computing tensor asynchronously in a graph. For example, a typical input architecture is to use a RandomShuffleQueue to prepare inputs for training a model:</p><ul><li>Multiple threads prepare training examples and push them in the queue.</li><li>A training thread executes a training op that dequeues mini-batches from the queue.</li></ul><p>This architecture simplifies the construction of input pipelines.</p><p><a href="https://github.com/SciSharp/TensorFlow.NET/blob/master/test/TensorFlowNET.UnitTest/QueueTest.cs">Download C# Example Code</a></p><p>From the above example, once the output gets to the point above you’ll actually have to terminate the program as it is blocked. Now, this isn’t very useful. What we really want to happen is for our little program to reload or enqueue more values whenever our queue is empty or is about to become empty. We could fix this by explicitly running our <em>enqueue_op</em> again in the code above to reload our queue with values. However, for large, more realistic programs, this will become unwieldy. Thankfully, TensorFlow has a solution.</p><p>TensorFlow provides two classes to help multi-threading task: tf.Coordinator and tf.QueueRunner. There two classes are designed to be used together. The Coordinator class helps multiple threads stop together and report exceptions to a main thread. The QueueRunner class is used to create a number of threads cooperating to enqueue tensors in the same queue.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6faef5e83b1" width="1" height="1" alt=""><hr><p><a href="https://medium.com/scisharp/queue-in-tensorflow-net-6faef5e83b1">Queue in TensorFlow .NET</a> was originally published in <a href="https://medium.com/scisharp">SciSharp STACK</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Convolution Neural Network in .NET]]></title>
            <link>https://medium.com/scisharp/convolution-neural-network-in-net-a1994dd1e236?source=rss-898fc824568e------2</link>
            <guid isPermaLink="false">https://medium.com/p/a1994dd1e236</guid>
            <category><![CDATA[image-recognition]]></category>
            <category><![CDATA[tensorflow]]></category>
            <category><![CDATA[mnist]]></category>
            <category><![CDATA[cnn]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Haiping Chen]]></dc:creator>
            <pubDate>Mon, 15 Jul 2019 03:05:57 GMT</pubDate>
            <atom:updated>2019-07-15T11:20:16.622Z</atom:updated>
            <content:encoded><![CDATA[<h3>Convolution Neural Network in .NET</h3><p>In this article, we’ll implement a simple Convolutional Neural Network model. We’ll implement this model to classify MNIST dataset.</p><p>The structure of the neural network we’re going to build is as follows. The hand-written digits images of the MNIST data which has 10 classes (from 0 to 9). The network is with 2 convolutional layers followed by 2 full-connected layers at the end.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1001/0*GDlFcyG1CV2OGEbX.png" /></figure><p>neural network architecture</p><p>Get started with the implementation:</p><ol><li><strong>Prepare data</strong></li></ol><p>MNIST is dataset of handwritten digits which contains 55,000 examples for training, 5,000 examples for validation and 10,000 example for testing. The digits have been size-normalized and centered in a fixed-size image (28 x 28 pixels) with values from 0 and 1.Each image has been flattened and converted to a 1-D array of 784 features. It’s also kind of benchmark of datasets for deep learning.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/255/0*Ma3_3sdMzQ6b2gD0.png" /></figure><p>We import <a href="https://github.com/SciSharp/TensorFlow.NET">TensorFlow.NET</a> and <a href="https://github.com/SciSharp/NumSharp">NumSharp</a> libraries.</p><pre>using System;<br>using NumSharp;<br>using Tensorflow;<br>using TensorFlowNET.Examples.Utility;<br>using static Tensorflow.Python;</pre><pre>const int img_h = 28;<br>const int img_w = 28;<br>int n_classes = 10; // Number of classes, one class per digit<br>int n_channels = 1;</pre><p>We’ll write the function which automatically loads the MNIST data and returns it in our desired shape and format. There is an MNIST data helper to make life easier.</p><pre>Datasets mnist;<br>public void PrepareData()<br>{<br>    mnist = MnistDataSet.read_data_sets(&quot;mnist&quot;, one_hot: true);<br>}</pre><p>Other than a function for loading the images and corresponding labels, we still need three more functions:</p><p><strong>reformat:</strong> reformats the data to the format acceptable for convolutional layer.</p><pre>private (NDArray, NDArray) Reformat(NDArray x, NDArray y)<br>{<br>    var (img_size, num_ch, num_class) = (np.sqrt(x.shape[1]), 1, len(np.unique&lt;int&gt;(np.argmax(y, 1))));<br>    var dataset = x.reshape(x.shape[0], img_size, img_size, num_ch).astype(np.float32);<br>    //y[0] = np.arange(num_class) == y[0];<br>    //var labels = (np.arange(num_class) == y.reshape(y.shape[0], 1, y.shape[1])).astype(np.float32);<br>    return (dataset, y);<br>}</pre><p><strong>randomize</strong>: which randomizes the order of images and their labels. At the beginning of each epoch, we will re-randomize the order of data samples to make sure that the trained model is not sensitive to the order of data.</p><pre>private (NDArray, NDArray) randomize(NDArray x, NDArray y)<br>{<br>    var perm = np.random.permutation(y.shape[0]);</pre><pre>np.random.shuffle(perm);<br>    return (mnist.train.images[perm], mnist.train.labels[perm]);<br>}</pre><p><strong>get_next_batch</strong>: which only selects a few number of images determined by the batch_size variable (as per Stochastic Gradient Descent method).</p><pre>private (NDArray, NDArray) get_next_batch(NDArray x, NDArray y, int start, int end)<br>{<br>    var x_batch = x[$&quot;{start}:{end}&quot;];<br>    var y_batch = y[$&quot;{start}:{end}&quot;];<br>    return (x_batch, y_batch);<br>}</pre><p><strong>2. Set Hyperparameters</strong></p><p>There’re about 55,000 images in training set, it takes a long time to calculate the gradient of the model using all there images. Therefore we use a small batch of images in each iteration of the optimizer by Stochastic Gradient Descent.</p><ul><li>epoch: one forward pass and one backward pass of all the training examples.</li><li>batch size: the number of training examples in one forward/backward pass. The higher the batch size, the more memory space you’ll need.</li><li>iteration: one forward pass and one backward pass of one batch of images the training examples.</li></ul><pre>int epochs = 10;<br>int batch_size = 100;<br>float learning_rate = 0.001f;<br>int display_freq = 200; // Frequency of displaying the training results</pre><p><strong>3. Network configuration</strong></p><p>1st convolutional layer:</p><pre>int filter_size1 = 5;  // Convolution filters are 5 x 5 pixels.<br>int num_filters1 = 16; //  There are 16 of these filters.<br>int stride1 = 1;  // The stride of the sliding window</pre><p>2nd convolutional layer:</p><pre>int filter_size2 = 5; // Convolution filters are 5 x 5 pixels.<br>int num_filters2 = 32;// There are 32 of these filters.<br>int stride2 = 1;  // The stride of the sliding window</pre><p>Fully-connected layer:</p><pre>h1 = 128  # Number of neurons in fully-connected layer.</pre><p><strong>4. Building the neural network</strong></p><p>Let’s make some functions to help build computation graph.</p><p><strong>variables</strong>: We need to define two variables W and b to construct our linear model. We use Tensorflow Variables of proper size and initialization to define them.</p><pre>// Create a weight variable with appropriate initialization<br>private RefVariable weight_variable(string name, int[] shape)<br>{<br>    var initer = tf.truncated_normal_initializer(stddev: 0.01f);<br>    return tf.get_variable(name,<br>                           dtype: tf.float32,<br>                           shape: shape,<br>                           initializer: initer);<br>}</pre><pre>// Create a bias variable with appropriate initialization<br>private RefVariable bias_variable(string name, int[] shape)<br>{<br>    var initial = tf.constant(0f, shape: shape, dtype: tf.float32);<br>    return tf.get_variable(name,<br>                           dtype: tf.float32,<br>                           initializer: initial);<br>}</pre><p><strong>2D convolution layer</strong>: This layer creates a convolution kernel that is convolved with the layer input to produce a tensor of outputs.</p><pre>private Tensor conv_layer(Tensor x, int filter_size, int num_filters, int stride, string name)<br>{<br>    return with(tf.variable_scope(name), delegate {</pre><pre>var num_in_channel = x.shape[x.NDims - 1];<br>        var shape = new[] { filter_size, filter_size, num_in_channel, num_filters };<br>        var W = weight_variable(&quot;W&quot;, shape);<br>        // var tf.summary.histogram(&quot;weight&quot;, W);<br>        var b = bias_variable(&quot;b&quot;, new[] { num_filters });<br>        // tf.summary.histogram(&quot;bias&quot;, b);<br>        var layer = tf.nn.conv2d(x, W,<br>                                 strides: new[] { 1, stride, stride, 1 },<br>                                 padding: &quot;SAME&quot;);<br>        layer += b;<br>        return tf.nn.relu(layer);<br>    });<br>}</pre><p><strong>max-pooling layer</strong>: Max pooling operation for temporal data.</p><pre>private Tensor max_pool(Tensor x, int ksize, int stride, string name)<br>{<br>    return tf.nn.max_pool(x,<br>                          ksize: new[] { 1, ksize, ksize, 1 },<br>                          strides: new[] { 1, stride, stride, 1 },<br>                          padding: &quot;SAME&quot;,<br>                          name: name);<br>}</pre><p><strong>flatten_layer</strong>: Flattens the output of the convolutional layer to be fed into fully-connected layer.</p><pre>private Tensor flatten_layer(Tensor layer)<br>{<br>    return with(tf.variable_scope(&quot;Flatten_layer&quot;), delegate<br>                {<br>                    var layer_shape = layer.TensorShape;<br>                    var num_features = layer_shape[new Slice(1, 4)].Size;<br>                    var layer_flat = tf.reshape(layer, new[] { -1, num_features });</pre><pre>return layer_flat;<br>                });<br>}</pre><p><strong>fully-connected layer</strong>: Neural network consists of stacks of fully-connected (dense) layers. Having the weight (W) and bias (b) variables, a fully-connected layer is defined as activation(W x X + b). The complete fc_layer function is as below:</p><pre>private Tensor fc_layer(Tensor x, int num_units, string name, bool use_relu = true)<br>{<br>    return with(tf.variable_scope(name), delegate<br>                {<br>                    var in_dim = x.shape[1];</pre><pre>var W = weight_variable(&quot;W_&quot; + name, shape: new[] { in_dim, num_units });<br>                    var b = bias_variable(&quot;b_&quot; + name, new[] { num_units });</pre><pre>var layer = tf.matmul(x, W) + b;<br>                    if (use_relu)<br>                        layer = tf.nn.relu(layer);</pre><pre>return layer;<br>                });<br>}</pre><p><strong>inputs</strong>: Now we need to define the proper tensors to feed in the input to our model. Placeholder variable is the suitable choice for the input images and corresponding labels. This allow us to change the inputs (images and labels) to the TensorFlow graph.</p><pre>with(tf.name_scope(&quot;Input&quot;), delegate<br>     {<br>         // Placeholders for inputs (x) and outputs(y)<br>         x = tf.placeholder(tf.float32, shape: (-1, img_h, img_w, n_channels), name: &quot;X&quot;);<br>         y = tf.placeholder(tf.float32, shape: (-1, n_classes), name: &quot;Y&quot;);<br>     });</pre><p>Placeholder y is the variable for the true labels associated with the images that were input in the placeholder variable x. It holds an arbitrary number of labels and each label is a vector of length num_classes which is 10.</p><p><strong>network layers</strong>: After creating the proper input, we have to pass it to our model. Since we have a neural network, we can stack multiple fully-connected layers using fc_layer method. Note that we will not use any activation function (use_relu = false) in the last layer. The reason is that we can use tf.nn.softmax_cross_entropy_with_logits to calculate the loss.</p><pre>var conv1 = conv_layer(x, filter_size1, num_filters1, stride1, name: &quot;conv1&quot;);<br>var pool1 = max_pool(conv1, ksize: 2, stride: 2, name: &quot;pool1&quot;);<br>var conv2 = conv_layer(pool1, filter_size2, num_filters2, stride2, name: &quot;conv2&quot;);<br>var pool2 = max_pool(conv2, ksize: 2, stride: 2, name: &quot;pool2&quot;);<br>var layer_flat = flatten_layer(pool2);<br>var fc1 = fc_layer(layer_flat, h1, &quot;FC1&quot;, use_relu: true);<br>var output_logits = fc_layer(fc1, n_classes, &quot;OUT&quot;, use_relu: false);</pre><p><strong>loss function, optimizer, accuracy, prediction</strong>: After creating the network, we have to calculate the loss and optimize it, we have to calculate the prediction and accuracy.</p><pre>with(tf.variable_scope(&quot;Train&quot;), delegate<br>     {</pre><pre>with(tf.variable_scope(&quot;Optimizer&quot;), delegate<br>              {<br>                  optimizer = tf.train.AdamOptimizer(learning_rate: learning_rate, name: &quot;Adam-op&quot;).minimize(loss);<br>              });</pre><pre>with(tf.variable_scope(&quot;Accuracy&quot;), delegate<br>              {<br>                  var correct_prediction = tf.equal(tf.argmax(output_logits, 1), tf.argmax(y, 1), name: &quot;correct_pred&quot;);<br>                  accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name: &quot;accuracy&quot;);<br>              });</pre><pre>with(tf.variable_scope(&quot;Prediction&quot;), delegate<br>              {<br>                  cls_prediction = tf.argmax(output_logits, axis: 1, name: &quot;predictions&quot;);<br>              });<br>     });</pre><p><strong>initialize variables</strong>: We have to invoke a variable initializer operation to initialize all variables.</p><pre>var init = tf.global_variables_initializer();</pre><p><strong>5. Train</strong></p><ol><li>After creating the graph, we can train our model. To train the model, we have to create a session and run the graph in the session.</li></ol><pre>// Number of training iterations in each epoch<br>var num_tr_iter = y_train.len / batch_size;</pre><pre>var init = tf.global_variables_initializer();<br>sess.run(init);</pre><pre>float loss_val = 100.0f;<br>float accuracy_val = 0f;</pre><pre>foreach (var epoch in range(epochs))<br>{<br>    print($&quot;Training epoch: {epoch + 1}&quot;);<br>    // Randomly shuffle the training data at the beginning of each epoch <br>    (x_train, y_train) = mnist.Randomize(x_train, y_train);</pre><pre>foreach (var iteration in range(num_tr_iter))<br>    {<br>        var start = iteration * batch_size;<br>        var end = (iteration + 1) * batch_size;<br>        var (x_batch, y_batch) = mnist.GetNextBatch(x_train, y_train, start, end);</pre><pre>// Run optimization op (backprop)<br>        sess.run(optimizer, new FeedItem(x, x_batch), new FeedItem(y, y_batch));</pre><pre>if (iteration % display_freq == 0)<br>        {<br>            // Calculate and display the batch loss and accuracy<br>            var result = sess.run(new[] { loss, accuracy }, new FeedItem(x, x_batch), new FeedItem(y, y_batch));<br>            loss_val = result[0];<br>            accuracy_val = result[1];<br>            print($&quot;iter {iteration.ToString(&quot;000&quot;)}: Loss={loss_val.ToString(&quot;0.0000&quot;)}, Training Accuracy={accuracy_val.ToString(&quot;P&quot;)}&quot;);<br>        }<br>    }</pre><pre>// Run validation after every epoch<br>    var results1 = sess.run(new[] { loss, accuracy }, new FeedItem(x, x_valid), new FeedItem(y, y_valid));<br>    loss_val = results1[0];<br>    accuracy_val = results1[1];<br>    print(&quot;---------------------------------------------------------&quot;);<br>    print($&quot;Epoch: {epoch + 1}, validation loss: {loss_val.ToString(&quot;0.0000&quot;)}, validation accuracy: {accuracy_val.ToString(&quot;P&quot;)}&quot;);<br>    print(&quot;---------------------------------------------------------&quot;);<br>}</pre><p><strong>6. Test</strong></p><p>After the training is done, we have to test our model to see how good it performs on a new dataset.</p><pre>public void Test(Session sess)<br>{<br>    var result = sess.run(new[] { loss, accuracy }, new FeedItem(x, x_test), new FeedItem(y, y_test));<br>    loss_test = result[0];<br>    accuracy_test = result[1];<br>    print(&quot;---------------------------------------------------------&quot;);<br>    print($&quot;Test loss: {loss_test.ToString(&quot;0.0000&quot;)}, test accuracy: {accuracy_test.ToString(&quot;P&quot;)}&quot;);<br> print(&quot;---------------------------------------------------------&quot;);<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/562/0*JzkdBD_pvfjwAWtw.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a1994dd1e236" width="1" height="1" alt=""><hr><p><a href="https://medium.com/scisharp/convolution-neural-network-in-net-a1994dd1e236">Convolution Neural Network in .NET</a> was originally published in <a href="https://medium.com/scisharp">SciSharp STACK</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Neural Network in TensorFlow.NET]]></title>
            <link>https://medium.com/scisharp/neural-network-in-tensorflow-net-1c3c4845bbee?source=rss-898fc824568e------2</link>
            <guid isPermaLink="false">https://medium.com/p/1c3c4845bbee</guid>
            <category><![CDATA[tensorflow]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[csharp]]></category>
            <dc:creator><![CDATA[Haiping Chen]]></dc:creator>
            <pubDate>Sun, 07 Jul 2019 04:24:01 GMT</pubDate>
            <atom:updated>2020-11-30T23:34:12.331Z</atom:updated>
            <content:encoded><![CDATA[<p>In this article, we’ll learn how to build a graph of neural network model in C#. The key advantage of neural network compared to Linear Classifier is that it can separate data which it not linearly separable. We’ll implement this model to classify hand-written digits images from the MNIST dataset.</p><p>The structure of the neural network we’re going to build is as follows. The hand-written digits images of the MNIST data which has 10 classes (from 0 to 9). The network is with 2 hidden layers: the first layer with 200 hidden units (neurons) and the second one (known as classifier layer) with 10 neurons.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vHhZ8UaxlXxqIqCKvknhAA.png" /></figure><p>Let’s get started with the implementation step by step:</p><p><strong>1. Prepare data</strong></p><p>MNIST is dataset of handwritten digits which contains 55,000 examples for training, 5,000 examples for validation and 10,000 example for testing. The digits have been size-normalized and centered in a fixed-size image (28 x 28 pixels) with values from 0 and 1.Each image has been flattened and converted to a 1-D array of 784 features. It’s also kind of benchmark of datasets for deep learning.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/255/1*pnL_FcWNlnK59dK0J6IOtg.png" /></figure><p>We define some variables makes it easier to modify them later. It’s important to note that in a linear model, we have to flatten the input images to a vector.</p><pre>using System;<br>using NumSharp;<br>using Tensorflow;<br>using TensorFlowNET.Examples.Utility;<br>using static Tensorflow.Python;</pre><pre>const int img_h = 28;<br>const int img_w = 28;<br>int img_size_flat = img_h * img_w; // 784, the total number of pixels<br>int n_classes = 10; // Number of classes, one class per digit</pre><p>We’ll write the function which automatically loads the MNIST data and returns it in our desired shape and format. There is an MNIST data helper to make life easier.</p><pre>Datasets mnist;<br>public void PrepareData()<br>{<br>    mnist = MnistDataSet.read_data_sets(&quot;mnist&quot;, one_hot: true);<br>}</pre><p>Other than a function for loading the images and corresponding labels, we still need two more functions:</p><p><strong>randomize</strong>: which randomizes the order of images and their labels. At the beginning of each epoch, we will re-randomize the order of data samples to make sure that the trained model is not sensitive to the order of data.</p><pre>private (NDArray, NDArray) randomize(NDArray x, NDArray y)<br>{<br>    var perm = np.random.permutation(y.shape[0]);</pre><pre>    np.random.shuffle(perm);<br>    return (mnist.train.images[perm], mnist.train.labels[perm]);<br>}</pre><p><strong>get_next_batch</strong>: which only selects a few number of images determined by the batch_size variable (as per Stochastic Gradient Descent method).</p><pre>private (NDArray, NDArray) get_next_batch(NDArray x, NDArray y, int start, int end)<br>{<br>    var x_batch = x[$&quot;{start}:{end}&quot;];<br>    var y_batch = y[$&quot;{start}:{end}&quot;];<br>    return (x_batch, y_batch);<br>}</pre><p><strong>2. Set Hyperparameters</strong></p><p>There’re about 55,000 images in training set, it takes a long time to calculate the gradient of the model using all there images. Therefore we use a small batch of images in each iteration of the optimizer by Stochastic Gradient Descent.</p><ul><li>epoch: one forward pass and one backward pass of all the training examples.</li><li>batch size: the number of training examples in one forward/backward pass. The higher the batch size, the more memory space you’ll need.</li><li>iteration: one forward pass and one backward pass of one batch of images the training examples.</li></ul><pre>int epochs = 10;<br>int batch_size = 100;<br>float learning_rate = 0.001f;<br>int h1 = 200; // number of nodes in the 1st hidden layer</pre><p><strong>3. Building the neural network</strong></p><p>Let’s make some functions to help build computation graph.</p><p><strong>variables</strong>: We need to define two variables W and b to construct our linear model. We use Tensorflow Variables of proper size and initialization to define them.</p><pre>// weight_variable<br>var in_dim = x.shape[1];</pre><pre>var initer = tf.truncated_normal_initializer(stddev: 0.01f);<br>var W = tf.get_variable(&quot;W_&quot; + name,<br>                        dtype: tf.float32,<br>                        shape: (in_dim, num_units),<br>                        initializer: initer);</pre><pre>// bias_variable<br>var initial = tf.constant(0f, num_units);<br>var b = tf.get_variable(&quot;b_&quot; + name,<br>                        dtype: tf.float32,<br>                        initializer: initial);</pre><p><strong>fully-connected layer</strong>: Neural network consists of stacks of fully-connected (dense) layers. Having the weight (W) and bias (b) variables, a fully-connected layer is defined as activation(W x X + b). The complete fc_layer function is as below:</p><pre>private Tensor fc_layer(Tensor x, int num_units, string name, bool use_relu = true)<br>{<br>    var in_dim = x.shape[1];</pre><pre>var initer = tf.truncated_normal_initializer(stddev: 0.01f);<br>    var W = tf.get_variable(&quot;W_&quot; + name,<br>                            dtype: tf.float32,<br>                            shape: (in_dim, num_units),<br>                            initializer: initer);</pre><pre>var initial = tf.constant(0f, num_units);<br>    var b = tf.get_variable(&quot;b_&quot; + name,<br>                            dtype: tf.float32,<br>                            initializer: initial);</pre><pre>var layer = tf.matmul(x, W) + b;<br>    if (use_relu)<br>        layer = tf.nn.relu(layer);</pre><pre>return layer;<br>}</pre><p><strong>inputs</strong>: Now we need to define the proper tensors to feed in the input to our model. Placeholder variable is the suitable choice for the input images and corresponding labels. This allow us to change the inputs (images and labels) to the TensorFlow graph.</p><pre>// Placeholders for inputs (x) and outputs(y)<br>x = tf.placeholder(tf.float32, shape: (-1, img_size_flat), name: &quot;X&quot;);<br>y = tf.placeholder(tf.float32, shape: (-1, n_classes), name: &quot;Y&quot;);</pre><p>Placeholder x is defined for the images, the shape is set to [None, img_size_flat], where None means that the tensor may hold an arbitrary number of images with each image being a vector of length img_size_flat.</p><p>Placeholder y is the variable for the true labels associated with the images that were input in the placeholder variable x. It holds an arbitrary number of labels and each label is a vector of length num_classes which is 10.</p><p><strong>network layers</strong>: After creating the proper input, we have to pass it to our model. Since we have a neural network, we can stack multiple fully-connected layers using fc_layer method. Note that we will not use any activation function (use_relu = false) in the last layer. The reason is that we can use tf.nn.softmax_cross_entropy_with_logits to calculate the loss.</p><pre>// Create a fully-connected layer with h1 nodes as hidden layer<br>var fc1 = fc_layer(x, h1, &quot;FC1&quot;, use_relu: true);<br>// Create a fully-connected layer with n_classes nodes as output layer<br>var output_logits = fc_layer(fc1, n_classes, &quot;OUT&quot;, use_relu: false);</pre><p><strong>loss function</strong>: After creating the network, we have to calculate the loss and optimize it, we have to calculate the correct_prediction and accuracy.</p><pre>// Define the loss function, optimizer, and accuracy<br>var logits = tf.nn.softmax_cross_entropy_with_logits(labels: y, logits: output_logits);</pre><pre>loss = tf.reduce_mean(logits, name: &quot;loss&quot;);</pre><pre>optimizer = tf.train.AdamOptimizer(learning_rate: learning_rate, name: &quot;Adam-op&quot;).minimize(loss);</pre><pre>var correct_prediction = tf.equal(tf.argmax(output_logits, 1), tf.argmax(y, 1), name: &quot;correct_pred&quot;);</pre><pre>accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name: &quot;accuracy&quot;);</pre><p><strong>initialize variables</strong>: We have to invoke a variable initializer operation to initialize all variables.</p><pre>var init = tf.global_variables_initializer();</pre><p>The complete computation graph is looks like below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*z0ehZfMH8Ipb56EUIGh4cQ.png" /></figure><p><strong>4. Train</strong></p><p>After creating the graph, we can train our model. To train the model, we have to create a session and run the graph in the session.</p><pre>// Number of training iterations in each epoch<br>var num_tr_iter = mnist.train.labels.len / batch_size;<br>with(tf.Session(), sess =&gt;<br>{<br>    sess.run(init);</pre><pre>float loss_val = 100.0f;<br>    float accuracy_val = 0f;</pre><pre>foreach (var epoch in range(epochs))<br>    {<br>        print($&quot;Training epoch: {epoch + 1}&quot;);<br>        // Randomly shuffle the training data at the beginning of each epoch <br>        var (x_train, y_train) = randomize(mnist.train.images, mnist.train.labels);</pre><pre>foreach (var iteration in range(num_tr_iter))<br>        {<br>            var start = iteration * batch_size;<br>            var end = (iteration + 1) * batch_size;<br>            var (x_batch, y_batch) = get_next_batch(x_train, y_train, start, end);</pre><pre>// Run optimization op (backprop)<br>            sess.run(optimizer, new FeedItem(x, x_batch), new FeedItem(y, y_batch));</pre><pre>if (iteration % display_freq == 0)<br>            {<br>                // Calculate and display the batch loss and accuracy<br>                var result = sess.run(new[] { loss, accuracy }, new FeedItem(x, x_batch), new FeedItem(y, y_batch));<br>                loss_val = result[0];<br>                accuracy_val = result[1];<br>                print($&quot;iter {iteration.ToString(&quot;000&quot;)}: Loss={loss_val.ToString(&quot;0.0000&quot;)}, Training Accuracy={accuracy_val.ToString(&quot;P&quot;)}&quot;);<br>            }<br>        }</pre><pre>// Run validation after every epoch<br>        var results1 = sess.run(new[] { loss, accuracy }, new FeedItem(x, mnist.validation.images), new FeedItem(y, mnist.validation.labels));<br>        loss_val = results1[0];<br>        accuracy_val = results1[1];<br>        print(&quot;---------------------------------------------------------&quot;);<br>        print($&quot;Epoch: {epoch + 1}, validation loss: {loss_val.ToString(&quot;0.0000&quot;)}, validation accuracy: {accuracy_val.ToString(&quot;P&quot;)}&quot;);<br>        print(&quot;---------------------------------------------------------&quot;);<br>    }<br>});</pre><p><strong>5. Test</strong></p><p>After the training is done, we have to test our model to see how good it performs on a new dataset.</p><pre>var result = sess.run(new[] { loss, accuracy }, new FeedItem(x, mnist.test.images),  new FeedItem(y, mnist.test.labels));<br>loss_test = result[0];<br>accuracy_test = result[1];<br>print(&quot;---------------------------------------------------------&quot;);<br>print($&quot;Test loss: {loss_test.ToString(&quot;0.0000&quot;)}, test accuracy: {accuracy_test.ToString(&quot;P&quot;)}&quot;);<br>print(&quot;---------------------------------------------------------&quot;);</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/979/1*Gg_q7p3ZdZUjwrcBR8Mdjw.png" /></figure><p>6. Plotting</p><p>TODO…</p><p>The source code is provided on <a href="https://github.com/SciSharp/SciSharp-Stack-Examples">Github</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1c3c4845bbee" width="1" height="1" alt=""><hr><p><a href="https://medium.com/scisharp/neural-network-in-tensorflow-net-1c3c4845bbee">Neural Network in TensorFlow.NET</a> was originally published in <a href="https://medium.com/scisharp">SciSharp STACK</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Running TensorFlow.NET in Jupyter Notebook]]></title>
            <link>https://medium.com/scisharp/running-tensorflow-net-in-jupyter-notebook-bef8c076efdc?source=rss-898fc824568e------2</link>
            <guid isPermaLink="false">https://medium.com/p/bef8c076efdc</guid>
            <category><![CDATA[csharp]]></category>
            <category><![CDATA[jupyter-notebook]]></category>
            <category><![CDATA[tensorflow]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Haiping Chen]]></dc:creator>
            <pubDate>Tue, 07 May 2019 02:26:44 GMT</pubDate>
            <atom:updated>2019-05-24T22:09:22.091Z</atom:updated>
            <content:encoded><![CDATA[<p>It’s cool we try to run <a href="https://github.com/SciSharp/TensorFlow.NET">TensorFlow.NET</a> in Jupyter Notebook.</p><p>By running SciSharp’s machine learning libraries on Jupyter Notebook, we can easily use .NET to develop and evaluate machine learning models without the need to install a cumbersome .NET development environment. The C# REPL (Read-Evaluate-Print-Loop) mode allows developers to use CSharp just like a scripting language.</p><p>To enable Jupyter to run C# REPL mode, we developed a new Jupyter Kernel <a href="https://github.com/SciSharp/ICSharpCore">ICSharpCore</a> that is responsible for the interaction between the Roslyn compiler and the Jupyter Server through the communication layer provided by ZeroMQ.</p><p>In the future we will try to run a complete machine learning model and integrate ploting capabilities.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/769/1*Mcmi6jsvVUXxsgk-_g90Hw.png" /></figure><p>Updated 05/18/2019</p><p>Now we have a complete example for Jupyter in .NET.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FtKYyjPCiKpM%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DtKYyjPCiKpM&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FtKYyjPCiKpM%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/919ed39b07f4415f192e2ef46d9bd2de/href">https://medium.com/media/919ed39b07f4415f192e2ef46d9bd2de/href</a></iframe><p>Updated 05/24/2019</p><p>Added the Plotting feature powered by <a href="https://github.com/SciSharp/Plot.NET">Plot.NET</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oJmyah59xxttFxDH8CJH9Q.png" /></figure><p>You can download the ipynb file from <a href="https://github.com/SciSharp/ICSharpCore/tree/master/samples">example</a> folder, or run it through <a href="https://github.com/SciSharp/SciSharpCube">SciSharp Cube</a> docker container in a few minutes.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bef8c076efdc" width="1" height="1" alt=""><hr><p><a href="https://medium.com/scisharp/running-tensorflow-net-in-jupyter-notebook-bef8c076efdc">Running TensorFlow.NET in Jupyter Notebook</a> was originally published in <a href="https://medium.com/scisharp">SciSharp STACK</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Conditional Statement Construction of TensorFlow in C#]]></title>
            <link>https://medium.com/scisharp/conditional-statement-construction-of-tensorflow-in-c-fe049b4a03c9?source=rss-898fc824568e------2</link>
            <guid isPermaLink="false">https://medium.com/p/fe049b4a03c9</guid>
            <category><![CDATA[csharp]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[tensorflow]]></category>
            <dc:creator><![CDATA[Haiping Chen]]></dc:creator>
            <pubDate>Sat, 13 Apr 2019 18:58:41 GMT</pubDate>
            <atom:updated>2019-04-15T01:27:36.615Z</atom:updated>
            <content:encoded><![CDATA[<p>Two weeks of hard work, we’re about to complete the conditional statement construction of TensorFlow in C#, Conditional operations are important data flow controls. We have even modified and recompiled the TensorFlow core library written in c++ in order to make the update input operation. Although the code still doesn’t work very well, it has already taken a big step forward.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gjjQq5v-doqyiDJjZSE_PA.png" /><figcaption>The incorrect one generated from TensorFlow.NET</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*94-bMhHSA_r7P99c2PVCIg.png" /><figcaption>The correct one generated from python binding</figcaption></figure><p>Thanks to the selfless contribution of the <a href="https://github.com/SciSharp">SciSharp</a> team, each of your lines of code is full of power.</p><p>Updated April 14, 2019</p><p>Fixed CondContext, and the unit test are all passed.</p><p>Snippet of code output “if x &lt; y then x * 17 else y + 23”</p><pre>[TestMethod]</pre><pre>public void testCondTrue()</pre><pre>{</pre><pre>  var graph = tf.Graph().as_default();</pre><pre>  with(tf.Session(graph), sess =&gt;</pre><pre>  {</pre><pre>    var x = tf.constant(2, name: &quot;x&quot;);</pre><pre>    var y = tf.constant(5, name: &quot;y&quot;);</pre><pre>    var z = control_flow_ops.cond(tf.less(x, y),</pre><pre>      () =&gt; tf.multiply(x, 17),</pre><pre>      () =&gt; tf.add(y, 23));</pre><pre>    int result = z.eval(sess);</pre><pre>    assertEquals(result, 34);</pre><pre>  });</pre><pre>}</pre><p>The detail can be checked from this <a href="https://github.com/SciSharp/TensorFlow.NET/issues/229">issue post</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fe049b4a03c9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/scisharp/conditional-statement-construction-of-tensorflow-in-c-fe049b4a03c9">Conditional Statement Construction of TensorFlow in C#</a> was originally published in <a href="https://medium.com/scisharp">SciSharp STACK</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>