Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7012 Articles
article-image-cloud-native-architectures-microservices-containers-serverless-part-1
Guest Contributor
13 Aug 2018
9 min read
Save for later

Modern Cloud Native architectures: Microservices, Containers, and Serverless - Part 1

Guest Contributor
13 Aug 2018
9 min read
This whitepaper is written by Mina Andrawos, an experienced engineer who has developed deep experience in the Go language, and modern software architectures. He regularly writes articles and tutorials about the Go language, and also shares open source projects. Mina Andrawos has authored the book Cloud Native programming with Golang, which provides practical techniques, code examples, and architectural patterns required to build cloud native microservices in the Go language.He is also the author of the Mastering Go Programming, and the Modern Golang Programming video courses. This paper sheds some light and provides practical exposure on some key topics in the modern software industry, namely cloud native applications.This includes microservices, containers , and serverless applications. The paper will cover the practical advantages, and disadvantages of the technologies covered. Microservices The microservices architecture has gained reputation as a powerful approach to architect modern software applications. So what are microservices? Microservices can be described as simply the idea of separating the functionality required from a software application into multiple independent small software services or “microservices.” Each microservice is responsible for an individual focused task. In order for microservices to collaborate together to form a large scalable application, they communicate and exchange data. Microservices were born out of the need to tame the complexity, and inflexibility of “monolithic” applications. A monolithic application is a type of application, where all required functionality is coded together into the same service. For example, here is a diagram representing a monolithic events (like concerts, shows..etc) booking application that takes care of the booking payment processing and event reservation: The application can be used by a customer to book a concert or a show. A user interface will be needed. Furthermore, we will also need a search functionality to look for events, a bookings handler to process the user booking then save it, and an events handler to help find the event, ensure it has seats available, then link it to the booking. In a production level application, more tasks will be needed like payment processing for example, but for now let’s focus on the four tasks outlined in the above figure. This monolithic application will work well with small to medium load. It will run on a single server, connect to a single database and will be written probably in the same programming language. Now, what will happen if the business grows exponentially and hundreds of thousands or millions of users need to be handled and processed? Initially, the short term solution would be to ensure that the server where the application runs, has powerful hardware specifications to withstand higher loads, and if not then add more memory, storage, and processing power to the server. This is called vertical scaling, which is the act of increasing the power of the hardware  like RAM and hard drive capacity to run heavy applications.However, this is typically not  sustainable in the long run as the load on the application continues to grow. Another challenge with monolithic applications is the inflexibility caused by being limited to only one or two programming languages. This inflexibility can affect the overall quality, and efficiency of the application. For example, node.js is a popular JavaScript framework for building web applications, whereas R is popular for data science applications. A monolithic application will make it difficult to utilize both technologies, whereas in a microservices application, we can simply build a data science service written in R and a web service written in Node.js. The microservices version of the events application will take the below form: This application will be capable of scaling among multiple servers, a practice known as horizontal scaling. Each service can be deployed on a different server with dedicated resources or in separate containers (more on that later). The different services can be written in different programming languages enabling greater flexibility, and different dedicated teams can focus on different services achieving more overall quality for the application. Another notable advantage of using microservices is the ease of continuous delivery, which is the ability to deploy software often, and at any time. The reason why microservices make continuous delivery easier is because a new feature deployed to one microservices is less likely to affect other microservices compared to monolithic applications. Issues with Microservices One notable drawback of relying heavily on microservices is the fact that they can become too complicated to manage in the long run as they grow in numbers and scope. There are approaches to mitigate this by utilizing monitoring tools such as Prometheus to detect problems, container technologies such as Docker to avoid pollutions of the host environments and avoiding over designing the services. However, these approaches take effort and time. Cloud native applications Microservices architectures are a natural fit for cloud native applications. A cloud native application is simply defined as an application built from the ground up for cloud computing architectures. This simply means that our application is cloud native, if we design it as if it is expected to be deployed on a distributed, and scalable infrastructure. For example, building an application with a redundant microservices architecture -we’ll see an example shortly- makes the application cloud native, since this architecture allows our application to be deployed in a distributed manner that allows it to be scalable and almost always available. A cloud native application does not need to always be deployed to a public cloud like AWS, we can deploy it to our own distributed cloud-like infrastructure instead if we have one. In fact, what makes an application fully cloud native is beyond just using microservices. Your application  should employ continuous delivery, which is your ability to continuously deliver updates to your production applications without  disruptions. Your application should also make use of services like message queues and technologies like containers, and serverless (containers and serverless are important topics for modern software architectures, so we’ll be discussing them in the next few sections). Cloud native applications assume access to numerous server nodes, having access to pre-deployed software services like message queues or load balancers, ease of integration with continuous delivery services, among other things. If you deploy your cloud native application to a commercial cloud like AWS or Azure, your application gets the option to utilize cloud only software services. For example, DynamoDB is a powerful database engine that can only be used on Amazon Web Services for production applications. Another example is the DocumentDB database in Azure. There are also cloud only message queues such as Amazon Simple Queue Service (SQS), which can be used to allow communication between microservices in the Amazon Web Services cloud. As mentioned earlier, cloud native microservices should be designed to allow redundancy between services. If we take the events booking application as an example, the application will look like this: Multiple server nodes would be allocated per microservice, allowing a redundant microservices architecture to be deployed. If the primary node or service fails for any reason, the secondary can take over ensuring lasting reliability and availability for cloud native applications. This availability is vital for fault intolerant applications such as e-commerce platforms, where downtime translates into large amounts of lost revenue. Cloud native applications provide great value for developers, enterprises, and startups. A notable tool worth mentioning in the world of microservices and cloud computing is Prometheus. Prometheus is an open source system monitoring and alerting tool that can be used to monitor complex microservices architectures and alert when an action needs to be taken. Prometheus was originally created by SoundCloud to monitor their systems, but then grew to become an independent project. The project is now a part of the cloud native computing foundation, which is a foundation tasked with building a sustainable ecosystem for cloud native applications. Cloud native limitations For cloud native applications, you will face some challenges if the need arises to migrate some or all of the applications. That is due to multiple reasons, depending on where your application is deployed. For example,if your cloud native application is deployed on a public cloud like AWS, cloud native APIs are not cross cloud platform. So, a DynamoDB database API utilized in an application will only work on AWS but not on Azure, since DynamoDB belongs exclusively to AWS. The API will also never work in a local environment because DynamoDB can only be utilized in AWS in production. Another reason is because there are some assumptions made when some cloud native applications are built, like the fact that there will be virtually unlimited number of server nodes to utilize when needed and that a new server node can be made available very quickly. These assumptions are sometimes hard to guarantee in a local data center environment, where real servers, networking hardware, and wiring need to be purchased. This brings us to the end of Part 1 of this whitepaper. Check out Part 2 tomorrow to learn about Containers and Serverless applications along with their practical advantages and limitations. About Author: Mina Andrawos Mina Andrawos is an experienced engineer who has developed deep experience in Go from using it personally and professionally. He regularly authors articles and tutorials about the language, and also shares Go's open source projects. He has written numerous Go applications with varying degrees of complexity. Other than Go, he has skills in Java, C#, Python, and C++. He has worked with various databases and software architectures. He is also skilled with the agile methodology for software development. Besides software development, he has working experience of scrum mastering, sales engineering, and software product management. Building microservices from a monolith Java EE app [Tutorial] 6 Ways to blow up your Microservices! Have Microservices killed the monolithic architecture? Maybe not!
Read more
  • 0
  • 0
  • 21139

article-image-tic-tac-toe-game-in-asp-net-core-tutorial
Aaron Lazar
13 Aug 2018
28 min read
Save for later

Building a Tic-tac-toe game in ASP.Net Core 2.0 [Tutorial]

Aaron Lazar
13 Aug 2018
28 min read
Learning is more fun if we do it while making games. With this thought, let's continue our quest to learn .NET Core 2.0 by writing a Tic-tac-toe game in .NET Core 2.0. We will develop the game in the ASP.NET Core 2.0 web app, using SignalR Core. We will follow a step-by-step approach and use Visual Studio 2017 as the primary IDE, but will list the steps needed while using the Visual Studio Code editor as well. Let's do the project setup first and then we will dive into the coding. This tutorial has been extracted from the book .NET Core 2.0 By Example, by Rishabh Verma and Neha Shrivastava. Installing SignalR Core NuGet package Create a new ASP.NET Core 2.0 MVC app named TicTacToeGame. With this, we will have a basic working ASP.NET Core 2.0 MVC app in place. However, to leverage SignalR Core in our app, we need to install SignalR Core NuGet and the client packages. To install the SignalR Core NuGet package, we can perform one of the following two approaches in the Visual Studio IDE: In the context menu of the TicTacToeGame project, click on Manage NuGet Packages. It will open the NuGet Package Manager for the project. In the Browse section, search for the Microsoft.AspNetCore.SignalR package and click Install. This will install SignalR Core in the app. Please note that currently the package is in the preview stage and hence the pre-release checkbox has to be ticked: Edit the TicTacToeGame.csproj file, add the following code snippet in the ItemGroup code containing package references, and click Save. As soon as the file is saved, the tooling will take care of restoring the packages and in a while, the SignalR package will be installed. This approach can be used with Visual Studio Code as well. Although Visual Studio Code detects the unresolved dependencies and may prompt you to restore the package, it is recommended that immediately after editing and saving the file, you run the dotnet restore command in the terminal window at the location of the project: <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.0.0-alpha1-final" /> </ItemGroup> Now we have server-side packages installed. We still need to install the client-side package of SignalR, which is available through npm. To do so, we need to first ascertain whether we have npm installed on the machine or not. If not, we need to install it. npm is distributed with Node.js, so we need to download and install Node.js from https://nodejs.org/en/. The installation is quite straightforward. Once this installation is done, open a Command Prompt at the project location and run the following command: npm install @aspnet/signalr-client This will install the SignalR client package. Just go to the package location (npm creates a node_modules folder in the project directory). The relative path from the project directory would be \node_modules\@aspnet\signalr-client\dist\browser. From this location, copy the signalr-client-1.0.0-alpha1-final.js file into the wwwroot\js folder. In the current version, the name is signalr-client-1.0.0-alpha1-final.js. With this, we are done with the project setup and we are ready to use SignalR goodness as well. So let's dive into the coding. Coding the game In this section, we will implement our gaming solution. The end output will be the working two-player Tic-Tac-Toe game. We will do the coding in steps for ease of understanding:  In the Startup class, we modify the ConfigureServices method to add SignalR to the container, by writing the following code: //// Adds SignalR to the services container. services.AddSignalR(); In the Configure method of the same class, we configure the pipeline to use SignalR and intercept and wire up the request containing gameHub to our SignalR hub that we will be creating with the following code: //// Use - SignalR & let it know to intercept and map any request having gameHub. app.UseSignalR(routes => { routes.MapHub<GameHub>("gameHub"); }); The following is the code for both methods, for the sake of clarity and completion. Other methods and properties are removed for brevity: // This method gets called by the run-time. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddMvc(); //// Adds SignalR to the services container. services.AddSignalR(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseBrowserLink(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); //// Use - SignalR & let it know to intercept and map any request having gameHub. app.UseSignalR(routes => { routes.MapHub<GameHub>("gameHub"); }); The previous two steps set up SignalR for us. Now, let's start with the coding of the player registration form. We want the player to be registered with a name and display the picture. Later, the server will also need to know whether the player is playing, waiting for a move, searching for an opponent, and so on. Let's create the Player model in the Models folder in the app. The code comments are self-explanatory: /// <summary> /// The player class. Each player of Tic-Tac-Toe game would be an instance of this class. /// </summary> internal class Player { /// <summary> /// Gets or sets the name of the player. This would be set at the time user registers. /// </summary> public string Name { get; set; } /// <summary> /// Gets or sets the opponent player. The player against whom the player would be playing. /// This is determined/ set when the players click Find Opponent Button in the UI. /// </summary> public Player Opponent { get; set; } /// <summary> /// Gets or sets a value indicating whether the player is playing. /// This is set when the player starts a game. /// </summary> public bool IsPlaying { get; set; } /// <summary> /// Gets or sets a value indicating whether the player is waiting for opponent to make a move. /// </summary> public bool WaitingForMove { get; set; } /// <summary> /// Gets or sets a value indicating whether the player is searching for opponent. /// </summary> public bool IsSearchingOpponent { get; set; } /// <summary> /// Gets or sets the time when the player registered. /// </summary> public DateTime RegisterTime { get; set; } /// <summary> /// Gets or sets the image of the player. /// This would be set at the time of registration, if the user selects the image. /// </summary> public string Image { get; set; } /// <summary> /// Gets or sets the connection id of the player connection with the gameHub. /// </summary> public string ConnectionId { get; set; } } Now, we need to have a UI in place so that the player can fill in the form and register. We also need to show the image preview to the player when he/she browses the image. To do so, we will use the Index.cshtml view of the HomeController class that comes with the default MVC template. We will refer to the following two .js files in the _Layout.cshtml partial view so that they are available to all the views. Alternatively, you could add these in the Index.cshtml view as well, but its highly recommended that common scripts should be added in _Layout.cshtml. The version of the script file may be different in your case. These are the currently available latest versions. Although jQuery is not required to be the library of choice for us, we will use jQuery to keep the code clean, simple, and compact. With these references, we have jQuery and SignalR available to us on the client side: <script src="~/lib/jquery/dist/jquery.js"></script> <!-- jQuery--> <script src="~/js/signalr-client-1.0.0-alpha1-final.js"></script> <!-- SignalR--> After adding these references, create the simple HTML UI for the image preview and registration, as follows: <div id="divPreviewImage"> <!-- To display the browsed image--> <fieldset> <div class="form-group"> <div class="col-lg-2"> <image src="" id="previewImage" style="height:100px;width:100px;border:solid 2px dotted; float:left" /> </div> <div class="col-lg-10" id="divOpponentPlayer"> <!-- To display image of opponent player--> <image src="" id="opponentImage" style="height:100px;width:100px;border:solid 2px dotted; float:right;" /> </div> </div> </fieldset> </div> <div id="divRegister"> <!-- Our Registration form--> <fieldset> <legend>Register</legend> <div class="form-group"> <label for="name" class="col-lg-2 control- label">Name</label> <div class="col-lg-10"> <input type="text" class="form-control" id="name" placeholder="Name"> </div> </div> <div class="form-group"> <label for="image" class="col-lg-2 control- label">Avatar</label> <div class="col-lg-10"> <input type="file" class="form-control" id="image" /> </div> </div> <div class="form-group"> <div class="col-lg-10 col-lg-offset-2"> <button type="button" class="btn btn-primary" id="btnRegister">Register</button> </div> </div> </fieldset> </div> When the player registers by clicking the Register button, the player's details need to be sent to the server. To do this, we will write the JavaScript to send details to our gameHub: let hubUrl = '/gameHub'; let httpConnection = new signalR.HttpConnection(hubUrl); let hubConnection = new signalR.HubConnection(httpConnection); var playerName = ""; var playerImage = ""; var hash = "#"; hubConnection.start(); $("#btnRegister").click(function () { //// Fires on button click playerName = $('#name').val(); //// Sets the player name with the input name. playerImage = $('#previewImage').attr('src'); //// Sets the player image variable with specified image var data = playerName.concat(hash, playerImage); //// The registration data to be sent to server. hubConnection.invoke('RegisterPlayer', data); //// Invoke the "RegisterPlayer" method on gameHub. }); $("#image").change(function () { //// Fires when image is changed. readURL(this); //// HTML 5 way to read the image as data url. }); function readURL(input) { if (input.files && input.files[0]) { //// Go in only if image is specified. var reader = new FileReader(); reader.onload = imageIsLoaded; reader.readAsDataURL(input.files[0]); } } function imageIsLoaded(e) { if (e.target.result) { $('#previewImage').attr('src', e.target.result); //// Sets the image source for preview. $("#divPreviewImage").show(); } }; The player now has a UI to input the name and image, see the preview image, and click Register. On clicking the Register button, we are sending the concatenated name and image to the gameHub on the server through hubConnection.invoke('RegisterPlayer', data);  So, it's quite simple for the client to make a call to the server. Initialize the hubConnection by specifying hub name as we did in the first three lines of the preceding code snippet. Start the connection by hubConnection.start();, and then invoke the server hub method by calling the invoke method, specifying the hub method name and the parameter it expects. We have not yet created the hub, so let's create the GameHub class on the server: /// <summary> /// The Game Hub class derived from Hub /// </summary> public class GameHub : Hub { /// <summary> /// To keep the list of all the connected players registered with the game hub. We could have /// used normal list but used concurrent bag as its thread safe. /// </summary> private static readonly ConcurrentBag<Player> players = new ConcurrentBag<Player>(); /// <summary> /// Registers the player with name and image. /// </summary> /// <param name="nameAndImageData">The name and image data sent by the player.</param> public void RegisterPlayer(string nameAndImageData) { var splitData = nameAndImageData?.Split(new char[] { '#' }, StringSplitOptions.None); string name = splitData[0]; string image = splitData[1]; var player = players?.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId); if (player == null) { player = new Player { ConnectionId = Context.ConnectionId, Name = name, IsPlaying = false, IsSearchingOpponent = false, RegisterTime = DateTime.UtcNow, Image = image }; if (!players.Any(j => j.Name == name)) { players.Add(player); } } this.OnRegisterationComplete(Context.ConnectionId); } /// <summary> /// Fires on completion of registration. /// </summary> /// <param name="connectionId">The connectionId of the player which registered</param> public void OnRegisterationComplete(string connectionId) { //// Notify this connection id that the registration is complete. this.Clients.Client(connectionId). InvokeAsync(Constants.RegistrationComplete); } } The code comments make it self-explanatory. The class should derive from the SignalR Hub class for it to be recognized as Hub. There are two methods of interest which can be overridden. Notice that both the methods follow the async pattern and hence return Task: Task OnConnectedAsync(): This method fires when a client/player connects to the hub. Task OnDisconnectedAsync(Exception exception): This method fires when a client/player disconnects or looses the connection. We will override this method to handle the scenario where the player disconnects. There are also a few properties that the hub class exposes: Context: This property is of type HubCallerContext and gives us access to the following properties: Connection: Gives access to the current connection User: Gives access to the ClaimsPrincipal of the user who is currently connected ConnectionId: Gives the current connection ID string Clients: This property is of type IHubClients and gives us the way to communicate to all the clients via the client proxy Groups: This property is of type IGroupManager and provides a way to add and remove connections to the group asynchronously To keep the things simple, we are not using a database to keep track of our registered players. Rather we will use an in-memory collection to keep the registered players. We could have used a normal list of players, such as List<Player>, but then we would need all the thread safety and use one of the thread safety primitives, such as lock, monitor, and so on, so we are going with ConcurrentBag<Player>, which is thread safe and reasonable for our game development. That explains the declaration of the players collection in the class. We will need to do some housekeeping to add players to this collection when they resister and remove them when they disconnect. We saw in previous step that the client invoked the RegisterPlayer method of the hub on the server, passing in the name and image data. So we defined a public method in our hub, named RegisterPlayer, accepting the name and image data string concatenated through #. This is just one of the simple ways of accepting the client data for demonstration purposes, we can also use strongly typed parameters. In this method, we split the string on # and extract the name as the first part and the image as the second part. We then check if the player with the current connection ID already exists in our players collection. If it doesn't, we create a Player object with default values and add them to our players collection. We are distinguishing the player based on the name for demonstration purposes, but we can add an Id property in the Player class and make different players have the same name also. After the registration is complete, the server needs to update the player, that the registration is complete and the player can then look for the opponent. To do so, we make a call to the OnRegistrationComplete method which invokes a method called  registrationComplete on the client with the current connection ID. Let's understand the code to invoke the method on the client: this.Clients.Client(connectionId).InvokeAsync(Constants.RegistrationComplete); On the Clients property, we can choose a client having a specific connection ID (in this case, the current connection ID from the Context) and then call InvokeAsync to invoke a method on the client specifying the method name and parameters as required. In the preceding case method, the name is registrationComplete with no parameters. Now we know how to invoke a server method from the client and also how to invoke the client method from the server. We also know how to select a specific client and invoke a method there. We can invoke the client method from the server, for all the clients, a group of clients, or a specific client, so rest of the coding stuff would be just a repetition of these two concepts. Next, we need to implement the registrationComplete method on the client. On registration completion, the registration form should be hidden and the player should be able to find an opponent to play against. To do so, we would write JavaScript code to hide the registration form and show the UI for finding the opponent. On clicking the Find Opponent button, we need the server to pair us against an opponent, so we need to invoke a hub method on server to find opponent. The server can respond us with two outcomes: It finds an opponent player to play against. In this case, the game can start so we need to simulate the coin toss, determine the player who can make the first move, and start the game. This would be a game board in the client-user interface. It doesn't find an opponent and asks the player to wait for another player to register and search for an opponent. This would be a no opponent found screen in the client. In both the cases, the server would do some processing and invoke a method on the client. Since we need a lot of different user interfaces for different scenarios, let's code the HTML markup inside div to make it easier to show and hide sections based on the server response. We will add the following code snippet in the body. The comments specify the purpose of each of the div elements and markup inside them: <div id="divFindOpponentPlayer"> <!-- Section to display Find Opponent --> <fieldset> <legend>Find a player to play against!</legend> <div class="form-group"> <input type="button" class="btn btn-primary" id="btnFindOpponentPlayer" value="Find Opponent Player" /> </div> </fieldset> </div> <div id="divFindingOpponentPlayer"> <!-- Section to display opponent not found, wait --> <fieldset> <legend>Its lonely here!</legend> <div class="form-group"> Looking for an opponent player. Waiting for someone to join! </div> </fieldset> </div> <div id="divGameInformation" class="form-group"> <!-- Section to display game information--> <div class="form-group" id="divGameInfo"></div> <div class="form-group" id="divInfo"></div> </div> <div id="divGame" style="clear:both"> <!-- Section where the game board would be displayed --> <fieldset> <legend>Game On</legend> <div id="divGameBoard" style="width:380px"></div> </fieldset> </div> The following client-side code would take care of Steps 7 and 8. Though the comments are self-explanatory, we will quickly see what all stuff is that is going on here. We handle the registartionComplete method and display the Find Opponent Player section. This section has a button to find an opponent player called btnFindOpponentPlayer. We define the event handler of the button to invoke the FindOpponent method on the hub. We will see the hub method implementation later, but we know that the hub method would either find an opponent or would not find an opponent, so we have defined the methods opponentFound and opponentNotFound, respectively, to handle these scenarios. In the opponentNotFound method, we just display a section in which we say, we do not have an opponent player. In the opponentFound method, we display the game section, game information section, opponent display picture section, and draw the Tic-Tac-Toe game board as a 3×3 grid using CSS styling. All the other sections are hidden: $("#btnFindOpponentPlayer").click(function () { hubConnection.invoke('FindOpponent'); }); hubConnection.on('registrationComplete', data => { //// Fires on registration complete. Invoked by server hub $("#divRegister").hide(); // hide the registration div $("#divFindOpponentPlayer").show(); // display find opponent player div. }); hubConnection.on('opponentNotFound', data => { //// Fires when no opponent is found. $('#divFindOpponentPlayer').hide(); //// hide the find opponent player section. $('#divFindingOpponentPlayer').show(); //// display the finding opponent player div. }); hubConnection.on('opponentFound', (data, image) => { //// Fires when opponent player is found. $('#divFindOpponentPlayer').hide(); $('#divFindingOpponentPlayer').hide(); $('#divGame').show(); //// Show game board section. $('#divGameInformation').show(); //// Show game information $('#divOpponentPlayer').show(); //// Show opponent player image. opponentImage = image; //// sets the opponent player image for display $('#opponentImage').attr('src', opponentImage); //// Binds the opponent player image $('#divGameInfo').html("<br/><span><strong> Hey " + playerName + "! You are playing against <i>" + data + "</i> </strong></span>"); //// displays the information of opponent that the player is playing against. //// Draw the tic-tac-toe game board, A 3x3 grid :) by proper styling. for (var i = 0; i < 9; i++) { $("#divGameBoard").append("<span class='marker' id=" + i + " style='display:block;border:2px solid black;height:100px;width:100px;float:left;margin:10px;'>" + i + "</span>"); } }); First we need to have a Game object to track a game, players involved, moves left, and check if there is a winner. We will have a Game class defined as per the following code. The comments detail the purpose of the methods and the properties defined: internal class Game { /// <summary> /// Gets or sets the value indicating whether the game is over. /// </summary> public bool IsOver { get; private set; } /// <summary> /// Gets or sets the value indicating whether the game is draw. /// </summary> public bool IsDraw { get; private set; } /// <summary> /// Gets or sets Player 1 of the game /// </summary> public Player Player1 { get; set; } /// <summary> /// Gets or sets Player 2 of the game /// </summary> public Player Player2 { get; set; } /// <summary> /// For internal housekeeping, To keep track of value in each of the box in the grid. /// </summary> private readonly int[] field = new int[9]; /// <summary> /// The number of moves left. We start the game with 9 moves remaining in a 3x3 grid. /// </summary> private int movesLeft = 9; /// <summary> /// Initializes a new instance of the <see cref="Game"/> class. /// </summary> public Game() { //// Initialize the game for (var i = 0; i < field.Length; i++) { field[i] = -1; } } /// <summary> /// Place the player number at a given position for a player /// </summary> /// <param name="player">The player number would be 0 or 1</param> /// <param name="position">The position where player number would be placed, should be between 0 and ///8, both inclusive</param> /// <returns>Boolean true if game is over and we have a winner.</returns> public bool Play(int player, int position) { if (this.IsOver) { return false; } //// Place the player number at the given position this.PlacePlayerNumber(player, position); //// Check if we have a winner. If this returns true, //// game would be over and would have a winner, else game would continue. return this.CheckWinner(); } } Now we have the entire game mystery solved with the Game class. We know when the game is over, we have the method to place the player marker, and check the winner. The following server side-code on the GameHub will handle Steps 7 and 8: /// <summary> /// The list of games going on. /// </summary> private static readonly ConcurrentBag<Game> games = new ConcurrentBag<Game>(); /// <summary> /// To simulate the coin toss. Like heads and tails, 0 belongs to one player and 1 to opponent. /// </summary> private static readonly Random toss = new Random(); /// <summary> /// Finds the opponent for the player and sets the Seraching for Opponent property of player to true. /// We will use the connection id from context to identify the current player. /// Once we have 2 players looking to play, we can pair them and simulate coin toss to start the game. /// </summary> public void FindOpponent() { //// First fetch the player from our players collection having current connection id var player = players.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId); if (player == null) { //// Since player would be registered before making this call, //// we should not reach here. If we are here, something somewhere in the flow above is broken. return; } //// Set that player is seraching for opponent. player.IsSearchingOpponent = true; //// We will follow a queue, so find a player who registered earlier as opponent. //// This would only be the case if more than 2 players are looking for opponent. var opponent = players.Where(x => x.ConnectionId != Context.ConnectionId && x.IsSearchingOpponent && !x.IsPlaying).OrderBy(x =>x.RegisterTime).FirstOrDefault(); if (opponent == null) { //// Could not find any opponent, invoke opponentNotFound method in the client. Clients.Client(Context.ConnectionId) .InvokeAsync(Constants.OpponentNotFound); return; } //// Set both players as playing. player.IsPlaying = true; player.IsSearchingOpponent = false; //// Make him unsearchable for opponent search opponent.IsPlaying = true; opponent.IsSearchingOpponent = false; //// Set each other as opponents. player.Opponent = opponent; opponent.Opponent = player; //// Notify both players that they can play by invoking opponentFound method for both the players. //// Also pass the opponent name and opoonet image, so that they can visualize it. //// Here we are directly using connection id, but group is a good candidate and use here. Clients.Client(Context.ConnectionId) .InvokeAsync(Constants.OpponentFound, opponent.Name, opponent.Image); Clients.Client(opponent.ConnectionId) .InvokeAsync(Constants.OpponentFound, player.Name, player.Image); //// Create a new game with these 2 player and add it to games collection. games.Add(new Game { Player1 = player, Player2 = opponent }); } Here, we have created a games collection to keep track of ongoing games and a Random field named toss to simulate the coin toss. How FindOpponent works is documented in the comments and is intuitive to understand. Once the game starts, each player has to make a move and then wait for the opponent to make a move, until the game ends. The move is made by clicking on the available grid cells. Here, we need to ensure that cell position that is already marked by one of the players is not changed or marked. So, as soon as a valid cell is marked, we set its CSS class to notAvailable so we know that the cell is taken. While clicking on a cell, we will check whether the cell has notAvailablestyle. If yes, it cannot be marked. If not, the cell can be marked and we then send the marked position to the server hub. We also see the waitingForMove, moveMade, gameOver, and opponentDisconnected events invoked by the server based on the game state. The code is commented and is pretty straightforward. The moveMade method in the following code makes use of the MoveInformation class, which we will define at the server for sharing move information with both players: //// Triggers on clicking the grid cell. $(document).on('click', '.marker', function () { if ($(this).hasClass("notAvailable")) { //// Cell is already taken. return; } hubConnection.invoke('MakeAMove', $(this)[0].id); //// Cell is valid, send details to hub. }); //// Fires when player has to make a move. hubConnection.on('waitingForMove', data => { $('#divInfo').html("<br/><span><strong> Your turn <i>" + playerName + "</i>! Make a winning move! </strong></span>"); }); //// Fires when move is made by either player. hubConnection.on('moveMade', data => { if (data.Image == playerImage) { //// Move made by player. $("#" + data.ImagePosition).addClass("notAvailable"); $("#" + data.ImagePosition).css('background-image', 'url(' + data.Image + ')'); $('#divInfo').html("<br/><strong>Waiting for <i>" + data.OpponentName + "</i> to make a move. </strong>"); } else { $("#" + data.ImagePosition).addClass("notAvailable"); $("#" + data.ImagePosition).css('background-image', 'url(' + data.Image + ')'); $('#divInfo').html("<br/><strong>Waiting for <i>" + data.OpponentName + "</i> to make a move. </strong>"); } }); //// Fires when the game ends. hubConnection.on('gameOver', data => { $('#divGame').hide(); $('#divInfo').html("<br/><span><strong>Hey " + playerName + "! " + data + " </strong></span>"); $('#divGameBoard').html(" "); $('#divGameInfo').html(" "); $('#divOpponentPlayer').hide(); }); //// Fires when the opponent disconnects. hubConnection.on('opponentDisconnected', data => { $("#divRegister").hide(); $('#divGame').hide(); $('#divGameInfo').html(" "); $('#divInfo').html("<br/><span><strong>Hey " + playerName + "! Your opponent disconnected or left the battle! You are the winner ! Hip Hip Hurray!!!</strong></span>"); }); After every move, both players need to be updated by the server about the move made, so that both players' game boards are in sync. So, on the server side we will need an additional model called MoveInformation, which will contain information on the latest move made by the player and the server will send this model to both the clients to keep them in sync: /// <summary> /// While playing the game, players would make moves. This class contains the information of those moves. /// </summary> internal class MoveInformation { /// <summary> /// Gets or sets the opponent name. /// </summary> public string OpponentName { get; set; } /// <summary> /// Gets or sets the player who made the move. /// </summary> public string MoveMadeBy { get; set; } /// <summary> /// Gets or sets the image position. The position in the game board (0-8) where the player placed his /// image. /// </summary> public int ImagePosition { get; set; } /// <summary> /// Gets or sets the image. The image of the player that he placed in the board (0-8) /// </summary> public string Image { get; set; } } Finally, we will wire up the remaining methods in the GameHub class to complete the game coding. The MakeAMove method is called every time a player makes a move. Also, we have overidden the OnDisconnectedAsync method to inform a player when their opponent disconnects. In this method, we also keep our players and games list current. The comments in the code explain the workings of the methods: /// <summary> /// Invoked by the player to make a move on the board. /// </summary> /// <param name="position">The position to place the player</param> public void MakeAMove(int position) { //// Lets find a game from our list of games where one of the player has the same connection Id as the current connection has. var game = games?.FirstOrDefault(x => x.Player1.ConnectionId == Context.ConnectionId || x.Player2.ConnectionId == Context.ConnectionId); if (game == null || game.IsOver) { //// No such game exist! return; } //// Designate 0 for player 1 int symbol = 0; if (game.Player2.ConnectionId == Context.ConnectionId) { //// Designate 1 for player 2. symbol = 1; } var player = symbol == 0 ? game.Player1 : game.Player2; if (player.WaitingForMove) { return; } //// Update both the players that move is made. Clients.Client(game.Player1.ConnectionId) .InvokeAsync(Constants.MoveMade, new MoveInformation { OpponentName = player.Name, ImagePosition = position, Image = player.Image }); Clients.Client(game.Player2.ConnectionId) .InvokeAsync(Constants.MoveMade, new MoveInformation { OpponentName = player.Name, ImagePosition = position, Image = player.Image }); //// Place the symbol and look for a winner after every move. if (game.Play(symbol, position)) { Remove<Game>(games, game); Clients.Client(game.Player1.ConnectionId) .InvokeAsync(Constants.GameOver, $"The winner is {player.Name}"); Clients.Client(game.Player2.ConnectionId) .InvokeAsync(Constants.GameOver, $"The winner is {player.Name}"); player.IsPlaying = false; player.Opponent.IsPlaying = false; this.Clients.Client(player.ConnectionId) .InvokeAsync(Constants.RegistrationComplete); this.Clients.Client(player.Opponent.ConnectionId) .InvokeAsync(Constants.RegistrationComplete); } //// If no one won and its a tame draw, update the players that the game is over and let them look for new game to play. if (game.IsOver && game.IsDraw) { Remove<Game>(games, game); Clients.Client(game.Player1.ConnectionId) .InvokeAsync(Constants.GameOver, "Its a tame draw!!!"); Clients.Client(game.Player2.ConnectionId) .InvokeAsync(Constants.GameOver, "Its a tame draw!!!"); player.IsPlaying = false; player.Opponent.IsPlaying = false; this.Clients.Client(player.ConnectionId) .InvokeAsync(Constants.RegistrationComplete); this.Clients.Client(player.Opponent.ConnectionId) .InvokeAsync(Constants.RegistrationComplete); } if (!game.IsOver) { player.WaitingForMove = !player.WaitingForMove; player.Opponent.WaitingForMove = !player.Opponent.WaitingForMove; Clients.Client(player.Opponent.ConnectionId) .InvokeAsync(Constants.WaitingForOpponent, player.Opponent.Name); Clients.Client(player.ConnectionId) .InvokeAsync(Constants.WaitingForOpponent, player.Opponent.Name); } } With this, we are done with the coding of the game and are ready to run the game app. So there you have it! You've just built your first game in .NET Core! The detailed source code can be downloaded from Github. If you're interested in learning more, head on over to get the book, .NET Core 2.0 By Example, by Rishabh Verma and Neha Shrivastava. Applying Single Responsibility principle from SOLID in .NET Core Unit Testing in .NET Core with Visual Studio 2017 for better code quality Get to know ASP.NET Core Web API [Tutorial]
Read more
  • 0
  • 1
  • 29195

article-image-web-services-functional-python-programming-tutorial
Aaron Lazar
12 Aug 2018
18 min read
Save for later

Writing web services with functional Python programming [Tutorial]

Aaron Lazar
12 Aug 2018
18 min read
In this article we'll understand how functional programming can be applied to web services in Python. This article is an extract from the 2nd edition of the bestseller, Functional Python Programming, written by Steven Lott. We'll look at a RESTful web service, which can slice and dice a source of data and provide downloads as JSON, XML, or CSV files. We'll provide an overall WSGI-compatible wrapper. The functions that do the real work of the application won't be narrowly constrained to fit the WSGI standard. We'll use a simple dataset with four subcollections: the Anscombe Quartet. It's a small set of data but it can be used to show the principles of a RESTful web service. We'll split our application into two tiers: a web tier, which will be a simple WSGI application, and data service tier, which will be more typical functional programming. We'll look at the web tier first so that we can focus on a functional approach to provide meaningful results. We need to provide two pieces of information to the web service: The quartet that we want: this is a slice and dice operation. The idea is to slice up the information by filtering and extracting meaningful subsets. The output format we want. The data selection is commonly done through the request path. We can request /anscombe/I/ or /anscombe/II/ to pick specific datasets from the quartet. The idea is that a URL defines a resource, and there's no good reason for the URL to ever change. In this case, the dataset selectors aren't dependent on dates or some organizational approval status, or other external factors. The URL is timeless and absolute. The output format is not a first-class part of the URL. It's just a serialization format, not the data itself. In some cases, the format is requested through the HTTP Accept header. This is hard to use from a browser, but easy to use from an application using a RESTful API. When extracting data from the browser, a query string is commonly used to specify the output format. We'll use the ?form=json method at the end of the path to specify the JSON output format. A URL we can use will look like this: http://localhost:8080/anscombe/III/?form=csv This would request a CSV download of the third dataset. Creating the Web Server Gateway Interface First, we'll use a simple URL pattern-matching expression to define the one and only routing in our application. In a larger or more complex application, we might have more than one such pattern: import re path_pat= re.compile(r"^/anscombe/(?P<dataset>.*?)/?$") This pattern allows us to define an overall script in the WSGI sense at the top level of the path. In this case, the script is anscombe. We'll take the next level of the path as a dataset to select from the Anscombe Quartet. The dataset value should be one of I, II, III, or IV. We used a named parameter for the selection criteria. In many cases, RESTful APIs are described using a syntax, as follows: /anscombe/{dataset}/ We translated this idealized pattern into a proper, regular expression, and preserved the name of the dataset selector in the path. Here are some example URL paths that demonstrate how this pattern works: >>> m1 = path_pat.match( "/anscombe/I" ) >>> m1.groupdict() {'dataset': 'I'} >>> m2 = path_pat.match( "/anscombe/II/" ) >>> m2.groupdict() {'dataset': 'II'} >>> m3 = path_pat.match( "/anscombe/" ) >>> m3.groupdict() {'dataset': ''} Each of these examples shows the details parsed from the URL path. When a specific series is named, this is located in the path. When no series is named, then an empty string is found by the pattern. Here's the overall WSGI application: import traceback import urllib.parse def anscombe_app( environ: Dict, start_response: SR_Func ) -> Iterable[bytes]: log = environ['wsgi.errors'] try: match = path_pat.match(environ['PATH_INFO']) set_id = match.group('dataset').upper() query = urllib.parse.parse_qs(environ['QUERY_STRING']) print(environ['PATH_INFO'], environ['QUERY_STRING'], match.groupdict(), file=log) dataset = anscombe_filter(set_id, raw_data()) content_bytes, mime = serialize( query['form'][0], set_id, dataset) headers = [ ('Content-Type', mime), ('Content-Length', str(len(content_bytes))), ] start_response("200 OK", headers) return [content_bytes] except Exception as e: # pylint: disable=broad-except traceback.print_exc(file=log) tb = traceback.format_exc() content = error_page.substitute( title="Error", message=repr(e), traceback=tb) content_bytes = content.encode("utf-8") headers = [ ('Content-Type', "text/html"), ('Content-Length', str(len(content_bytes))), ] start_response("404 NOT FOUND", headers) return [content_bytes] This application will extract two pieces of information from the request: the PATH_INFO and the QUERY_STRING keys in the environment dictionary. The PATH_INFO request will define which set to extract. The QUERY_STRING request will specify an output format. It's important to note that query strings can be quite complex. Rather than assume it is simply a string like ?form=json, we've used the urllib.parse module to properly locate all of the name-value pairs in the query string. The value with the 'form' key in the dictionary extracted from the query string can be found in query['form'][0]. This should be one of the defined formats. If it isn't, an exception will be raised, and an error page displayed. After locating the path and query string, the application processing is highlighted in bold. These two statements rely on three functions to gather, filter, and serialize the results: The raw_data() function reads the raw data from a file. The result is a dictionary with lists of Pair objects. The anscombe_filter() function accepts a selection string and the dictionary of raw data and returns a single list of Pair objects. The list of pairs is then serialized into bytes by the serialize() function. The serializer is expected to produce byte's, which can then be packaged with an appropriate header, and returned. We elected to produce an HTTP Content-Length header as part of the result. This header isn't required, but it's polite for large downloads. Because we decided to emit this header, we are forced to create a bytes object with the serialization of the data so we can count the bytes. If we elected to omit the Content-Length header, we could change the structure of this application dramatically. Each serializer could be changed to a generator function, which would yield bytes as they are produced. For large datasets, this can be a helpful optimization. For the user watching a download, however, it might not be so pleasant because the browser can't display how much of the download is complete. A common optimization is to break the transaction into two parts. The first part computes the result and places a file into a Downloads directory. The response is a 302 FOUND with a Location header that identifies the file to download. Generally, most clients will then request the file based on this initial response. The file can be downloaded by Apache httpd or Nginx without involving the Python application. For this example, all errors are treated as a 404 NOT FOUND error. This could be misleading, since a number of individual things might go wrong. More sophisticated error handling could give more try:/except: blocks to provide more informative feedback. For debugging purposes, we've provided a Python stack trace in the resulting web page. Outside the context of debugging, this is a very bad idea. Feedback from an API should be just enough to fix the request, and nothing more. A stack trace provides too much information to potentially malicious users. Getting raw data Here's what we're using for this application: from Chapter_3.ch03_ex5 import ( series, head_map_filter, row_iter) from typing import ( NamedTuple, Callable, List, Tuple, Iterable, Dict, Any) RawPairIter = Iterable[Tuple[float, float]] class Pair(NamedTuple): x: float y: float pairs: Callable[[RawPairIter], List[Pair]] \ = lambda source: list(Pair(*row) for row in source) def raw_data() -> Dict[str, List[Pair]]: with open("Anscombe.txt") as source: data = tuple(head_map_filter(row_iter(source))) mapping = { id_str: pairs(series(id_num, data)) for id_num, id_str in enumerate( ['I', 'II', 'III', 'IV']) } return mapping The raw_data() function opens the local data file, and applies the row_iter() function to return each line of the file parsed into a row of separate items. We applied the head_map_filter() function to remove the heading from the file. The result created a tuple-of-list structure, which is assigned the variable data. This handles parsing the input into a structure that's useful. The resulting structure is an instance of the Pair subclass of the NamedTuple class, with two fields that have float as their type hints. We used a dictionary comprehension to build the mapping from id_str to pairs assembled from the results of the series() function. The series() function extracts (x, y) pairs from the input document. In the document, each series is in two adjacent columns. The series named I is in columns zero and one; the series() function extracts the relevant column pairs. The pairs() function is created as a lambda object because it's a small generator function with a single parameter. This function builds the desired NamedTuple objects from the sequence of anonymous tuples created by the series() function. Since the output from the raw_data() function is a mapping, we can do something like the following example to pick a specific series by name: >>> raw_data()['I'] [Pair(x=10.0, y=8.04), Pair(x=8.0, y=6.95), ... Given a key, for example, 'I', the series is a list of Pair objects that have the x, y values for each item in the series. Applying a filter In this application, we're using a simple filter. The entire filter process is embodied in the following function: def anscombe_filter( set_id: str, raw_data_map: Dict[str, List[Pair]] ) -> List[Pair]: return raw_data_map[set_id] We made this trivial expression into a function for three reasons: The functional notation is slightly more consistent and a bit more flexible than the subscript expression We can easily expand the filtering to do more We can include separate unit tests in the docstring for this function While a simple lambda would work, it wouldn't be quite as convenient to test. For error handling, we've done exactly nothing. We've focused on what's sometimes called the happy path: an ideal sequence of events. Any problems that arise in this function will raise an exception. The WSGI wrapper function should catch all exceptions and return an appropriate status message and error response content. For example, it's possible that the set_id method will be wrong in some way. Rather than obsess over all the ways it could be wrong, we'll simply allow Python to throw an exception. Indeed, this function follows the Python advice that, it's better to seek forgiveness than to ask permission. This advice is materialized in code by avoiding permission-seeking: there are no preparatory if statements that seek to qualify the arguments as valid. There is only forgiveness handling: an exception will be raised and handled in the WSGI wrapper. This essential advice applies to the preceding raw data and the serialization that we will see now. Serializing the results Serialization is the conversion of Python data into a stream of bytes, suitable for transmission. Each format is best described by a simple function that serializes just that one format. A top-level generic serializer can then pick from a list of specific serializers. The picking of serializers leads to the following collection of functions: Serializer = Callable[[str, List[Pair]], bytes] SERIALIZERS: Dict[str, Tuple[str, Serializer]]= { 'xml': ('application/xml', serialize_xml), 'html': ('text/html', serialize_html), 'json': ('application/json', serialize_json), 'csv': ('text/csv', serialize_csv), } def serialize( format: str, title: str, data: List[Pair] ) -> Tuple[bytes, str]: mime, function = SERIALIZERS.get( format.lower(), ('text/html', serialize_html)) return function(title, data), mime The overall serialize() function locates a specific serializer in the SERIALIZERS dictionary, which maps a format name to a two-tuple. The tuple has a MIME type that must be used in the response to characterize the results. The tuple also has a function based on the Serializer type hint. This function will transform a name and a list of Pair objects into bytes that will be downloaded. The serialize() function doesn't do any data transformation. It merely maps a name to a function that does the hard work of transformation. Returning a function permits the overall application to manage the details of memory or file-system serialization. Serializing to the file system, while slow, permits larger files to be handled. We'll look at the individual serializers below. The serializers fall into two groups: those that produce strings and those that produce bytes. A serializer that produces a string will need to have the string encoded as bytes for download. A serializer that produces bytes doesn't need any further work. For the serializers, which produce strings, we can use function composition with a standardized convert-to-bytes function. Here's a decorator that can standardize the conversion to bytes: from typing import Callable, TypeVar, Any, cast from functools import wraps def to_bytes( function: Callable[..., str] ) -> Callable[..., bytes]: @wraps(function) def decorated(*args, **kw): text = function(*args, **kw) return text.encode("utf-8") return cast(Callable[..., bytes], decorated) We've created a small decorator named @to_bytes. This will evaluate the given function and then encode the results using UTF-8 to get bytes. Note that the decorator changes the decorated function from having a return type of str to a return type of bytes. We haven't formally declared parameters for the decorated function, and used ... instead of the details. We'll show how this is used with JSON, CSV, and HTML serializers. The XML serializer produces bytes directly and doesn't need to be composed with this additional function. We could also do the functional composition in the initialization of the serializers mapping. Instead of decorating the function definition, we could decorate the reference to the function object. Here's an alternative definition for the serializer mapping: SERIALIZERS = { 'xml': ('application/xml', serialize_xml), 'html': ('text/html', to_bytes(serialize_html)), 'json': ('application/json', to_bytes(serialize_json)), 'csv': ('text/csv', to_bytes(serialize_csv)), } This replaces decoration at the site of the function definition with decoration when building this mapping data structure. It seems potentially confusing to defer the decoration. Serializing data into JSON or CSV formats The JSON and CSV serializers are similar because both rely on Python's libraries to serialize. The libraries are inherently imperative, so the function bodies are strict sequences of statements. Here's the JSON serializer: import json @to_bytes def serialize_json(series: str, data: List[Pair]) -> str: """ >>> data = [Pair(2,3), Pair(5,7)] >>> serialize_json( "test", data ) b'[{"x": 2, "y": 3}, {"x": 5, "y": 7}]' """ obj = [dict(x=r.x, y=r.y) for r in data] text = json.dumps(obj, sort_keys=True) return text We created a list-of-dict structure and used the json.dumps() function to create a string representation. The JSON module requires a materialized list object; we can't provide a lazy generator function. The sort_keys=True argument value is helpful for unit testing. However, it's not required for the application and represents a bit of overhead. Here's the CSV serializer: import csv import io @to_bytes def serialize_csv(series: str, data: List[Pair]) -> str: """ >>> data = [Pair(2,3), Pair(5,7)] >>> serialize_csv("test", data) b'x,y\\r\\n2,3\\r\\n5,7\\r\\n' """ buffer = io.StringIO() wtr = csv.DictWriter(buffer, Pair._fields) wtr.writeheader() wtr.writerows(r._asdict() for r in data) return buffer.getvalue() The CSV module's readers and writers are a mixture of imperative and functional elements. We must create the writer, and properly create headings in a strict sequence. We've used the _fields attribute of the Pair namedtuple to determine the column headings for the writer. The writerows() method of the writer will accept a lazy generator function. In this case, we used the _asdict() method of each Pair object to return a dictionary suitable for use with the CSV writer. Serializing data into XML We'll look at one approach to XML serialization using the built-in libraries. This will build a document from individual tags. A common alternative approach is to use Python introspection to examine and map Python objects and class names to XML tags and attributes. Here's our XML serialization: import xml.etree.ElementTree as XML def serialize_xml(series: str, data: List[Pair]) -> bytes: """ >>> data = [Pair(2,3), Pair(5,7)] >>> serialize_xml( "test", data ) b'<series name="test"><row><x>2</x><y>3</y></row><row><x>5</x><y>7</y></row></series>' """ doc = XML.Element("series", name=series) for row in data: row_xml = XML.SubElement(doc, "row") x = XML.SubElement(row_xml, "x") x.text = str(row.x) y = XML.SubElement(row_xml, "y") y.text = str(row.y) return cast(bytes, XML.tostring(doc, encoding='utf-8')) We created a top-level element, <series>, and placed <row> sub-elements underneath that top element. Within each <row> sub-element, we've created <x> and <y> tags, and assigned text content to each tag. The interface for building an XML document using the ElementTree library tends to be heavily imperative. This makes it a poor fit for an otherwise functional design. In addition to the imperative style, note that we haven't created a DTD or XSD. We have not properly assigned a namespace to our tags. We also omitted the <?xml version="1.0"?> processing instruction that is generally the first item in an XML document. The XML.tostring() function has a type hint that states it returns str. This is generally true, but when we provide the encoding parameter, the result type changes to bytes. There's no easy way to formalize the idea of variant return types based on parameter values, so we use an explicit cast() to inform mypy of the actual type. A more sophisticated serialization library could be helpful here. There are many to choose from. Visit https://wiki.python.org/moin/PythonXml for a list of alternatives. Serializing data into HTML In our final example of serialization, we'll look at the complexity of creating an HTML document. The complexity arises because in HTML, we're expected to provide an entire web page with a great deal of context information. Here's one way to tackle this HTML problem: import string data_page = string.Template("""\ <html> <head><title>Series ${title}</title></head> <body> <h1>Series ${title}</h1> <table> <thead><tr><td>x</td><td>y</td></tr></thead> <tbody> ${rows} </tbody> </table> </body> </html> """) @to_bytes def serialize_html(series: str, data: List[Pair]) -> str: """ >>> data = [Pair(2,3), Pair(5,7)] >>> serialize_html("test", data) #doctest: +ELLIPSIS b'<html>...<tr><td>2</td><td>3</td></tr>\\n<tr><td>5</td><td>7</td></tr>... """ text = data_page.substitute( title=series, rows="\n".join( "<tr><td>{0.x}</td><td>{0.y}</td></tr>".format(row) for row in data) ) return text Our serialization function has two parts. The first part is a string.Template() function that contains the essential HTML page. It has two placeholders where data can be inserted into the template. The ${title} method shows where title information can be inserted, and the ${rows} method shows where the data rows can be inserted. The function creates individual data rows using a simple format string. These are joined into a longer string, which is then substituted into the template. While workable for simple cases like the preceding example, this isn't ideal for more complex result sets. There are a number of more sophisticated template tools to create HTML pages. A number of these include the ability to embed the looping in the template, separate from the function that initializes serialization. If you found this tutorial useful and would like to learn more such techniques, head over to get Steven Lott's bestseller, Functional Python Programming. What is the difference between functional and object-oriented programming? Should you move to Python 3? 7 Python experts’ opinions Is Python edging R out in the data science wars?
Read more
  • 0
  • 0
  • 21281

article-image-implement-rnn-tensorflow-spam-prediction-tutorial
Packt Editorial Staff
11 Aug 2018
11 min read
Save for later

Implementing RNN in TensorFlow for spam prediction [Tutorial]

Packt Editorial Staff
11 Aug 2018
11 min read
Artificial neural networks (ANN) are an abstract representation of the human nervous system, which contains a collection of neurons that communicate with each other through connections called axons. A recurrent neural network (RNN) is a class of ANN where connections between units form a directed cycle. RNNs make use of information from the past. That way, they can make predictions in data with high temporal dependencies. This creates an internal state of the network, which allows it to exhibit dynamic temporal behavior. In this article we will look at: Implementation of basic RNNs in TensorFlow. An example of how to implement an RNN in TensorFlow for spam predictions. Train a model that will learn to distinguish between spam and non-spam emails using the text of the email. This article is an extract taken from the book Deep Learning with TensorFlow – Second Edition, written by Giancarlo Zaccone, Md. Rezaul Karim. Implementing basic RNNs in TensorFlow TensorFlow has tf.contrib.rnn.BasicRNNCell and tf.nn.rnn_cell. BasicRNNCell, which provide the basic building blocks of RNNs. However, first let's implement a very simple RNN model, without using either of these. The idea is to have a better understanding of what goes on under the hood. We will create an RNN composed of a layer of five recurrent neurons using the ReLU activation function. We will assume that the RNN runs over only two-time steps, taking input vectors of size 3 at each time step. The following code builds this RNN, unrolled through two-time steps: n_inputs = 3 n_neurons = 5 X1 = tf.placeholder(tf.float32, [None, n_inputs]) X2 = tf.placeholder(tf.float32, [None, n_inputs]) Wx = tf.get_variable("Wx", shape=[n_inputs,n_neurons], dtype=tf. float32, initializer=None, regularizer=None, trainable=True, collections=None) Wy = tf.get_variable("Wy", shape=[n_neurons,n_neurons], dtype=tf. float32, initializer=None, regularizer=None, trainable=True, collections=None) b = tf.get_variable("b", shape=[1,n_neurons], dtype=tf.float32, initializer=None, regularizer=None, trainable=True, collections=None) Y1 = tf.nn.relu(tf.matmul(X1, Wx) + b) Y2 = tf.nn.relu(tf.matmul(Y1, Wy) + tf.matmul(X2, Wx) + b) Then we initialize the global variables as follows: init_op = tf.global_variables_initializer() This network looks much like a two-layer feedforward neural network, but both layers share the same weights and bias vectors. Additionally, we feed inputs at each layer and receive outputs from each layer. X1_batch = np.array([[0, 2, 3], [2, 8, 9], [5, 3, 8], [3, 2, 9]]) # t = 0 X2_batch = np.array([[5, 6, 8], [1, 0, 0], [8, 2, 0], [2, 3, 6]]) # t = 1 These mini-batches contain four instances, each with an input sequence composed of exactly two inputs. At the end, Y1_val and Y2_val contain the outputs of the network at both time steps for all neurons and all instances in the mini-batch. Then we create a TensorFlow session and execute the computational graph as follows: with tf.Session() as sess:        init_op.run()        Y1_val, Y2_val = sess.run([Y1, Y2], feed_dict={X1:        X1_batch, X2: X2_batch}) Finally, we print the result: print(Y1_val) # output at t = 0 print(Y2_val) # output at t = 1 The following is the output: >>> [[ 0. 0. 0. 2.56200171 1.20286 ] [ 0. 0. 0. 12.39334488 2.7824254 ] [ 0. 0. 0. 13.58520699 5.16213894] [ 0. 0. 0. 9.95982838 6.20652485]] [[ 0. 0. 0. 14.86255169 6.98305273] [ 0. 0. 26.35326385 0.66462421 18.31009483] [ 5.12617588 4.76199865 20.55905533 11.71787453 18.92538261] [ 0. 0. 19.75175095 3.38827515 15.98449326]] The network we created is simple, but if you run it over 100 time steps, for example, the graph is going to be very big. Implementing an RNN for spam prediction In this section, we will see how to implement an RNN in TensorFlow to predict spam/ham from texts. Data description and preprocessing The popular spam dataset from the UCI ML repository will be used, which can be downloaded from http://archive.ics.uci.edu/ml/machine-learning-databases/00228/smsspamcollection.zip. The dataset contains texts from several emails, some of which were marked as spam. Here we will train a model that will learn to distinguish between spam and non-spam emails using only the text of the email. Let's get started by importing the required libraries and model: import os import re import io import requests import numpy as np import matplotlib.pyplot as plt import tensorflow as tf from zipfile import ZipFile from tensorflow.python.framework import ops import warnings Additionally, we can stop printing the warning produced by TensorFlow if you want: warnings.filterwarnings("ignore") os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' ops.reset_default_graph() Now, let's create the TensorFlow session for the graph: sess = tf.Session() The next task is setting the RNN parameters: epochs = 300 batch_size = 250 max_sequence_length = 25 rnn_size = 10 embedding_size = 50 min_word_frequency = 10 learning_rate = 0.0001 dropout_keep_prob = tf.placeholder(tf.float32) Let's manually download the dataset and store it in a text_data.txt file in the temp directory. First, we set the path: data_dir = 'temp' data_file = 'text_data.txt' if not os.path.exists(data_dir):    os.makedirs(data_dir) Now, we directly download the dataset in zipped format: if not os.path.isfile(os.path.join(data_dir, data_file)):    zip_url = 'http://archive.ics.uci.edu/ml/machine-learning- databases/00228/smsspamcollection.zip'    r = requests.get(zip_url)    z = ZipFile(io.BytesIO(r.content))    file = z.read('SMSSpamCollection') We still need to format the data: text_data = file.decode()    text_data = text_data.encode('ascii',errors='ignore')    text_data = text_data.decode().split('\n') Now, store in it the directory mentioned earlier in a text file: with open(os.path.join(data_dir, data_file), 'w') as file_conn:        for text in text_data:            file_conn.write("{}\n".format(text)) else:    text_data = []    with open(os.path.join(data_dir, data_file), 'r') as file_conn:        for row in file_conn:            text_data.append(row)    text_data = text_data[:-1] Let's split the words that have a word length of at least 2: text_data = [x.split('\t') for x in text_data if len(x)>=1] [text_data_target, text_data_train] = [list(x) for x in zip(*text_data)] Now we create a text cleaning function: def clean_text(text_string):    text_string = re.sub(r'([^\s\w]|_|[0-9])+', '', text_string)    text_string = " ".join(text_string.split())    text_string = text_string.lower()    return(text_string) We call the preceding method to clean the text: text_data_train = [clean_text(x) for x in text_data_train] Now we need to do one of the most important tasks, which is creating word embedding –changing text into numeric vectors: vocab_processor = tf.contrib.learn.preprocessing.VocabularyProcessor(max_sequence_length, min_frequency=min_word_frequency) text_processed = np.array(list(vocab_processor.fit_transform(text_data_train))) Now let's shuffle to make the dataset balance: text_processed = np.array(text_processed) text_data_target = np.array([1 if x=='ham' else 0 for x in text_data_target]) shuffled_ix = np.random.permutation(np.arange(len(text_data_target))) x_shuffled = text_processed[shuffled_ix] y_shuffled = text_data_target[shuffled_ix] Now that we have shuffled the data, we can split the data into a training and testing set: ix_cutoff = int(len(y_shuffled)*0.75) x_train, x_test = x_shuffled[:ix_cutoff], x_shuffled[ix_cutoff:] y_train, y_test = y_shuffled[:ix_cutoff], y_shuffled[ix_cutoff:] vocab_size = len(vocab_processor.vocabulary_) print("Vocabulary size: {:d}".format(vocab_size)) print("Training set size: {:d}".format(len(y_train))) print("Test set size: {:d}".format(len(y_test))) Following is the output of the preceding code: >>> Vocabulary size: 933 Training set size: 4180 Test set size: 1394 Before we start training, let's create placeholders for our TensorFlow graph: x_data = tf.placeholder(tf.int32, [None, max_sequence_length]) y_output = tf.placeholder(tf.int32, [None]) Let's create the embedding: embedding_mat = tf.get_variable("embedding_mat", shape=[vocab_size, embedding_size], dtype=tf.float32, initializer=None, regularizer=None, trainable=True, collections=None) embedding_output = tf.nn.embedding_lookup(embedding_mat, x_data) Now it's time to construct our RNN. The following code defines the RNN cell: cell = tf.nn.rnn_cell.BasicRNNCell(num_units = rnn_size) output, state = tf.nn.dynamic_rnn(cell, embedding_output, dtype=tf.float32) output = tf.nn.dropout(output, dropout_keep_prob) Now let's define the way to get the output from our RNN sequence: output = tf.transpose(output, [1, 0, 2]) last = tf.gather(output, int(output.get_shape()[0]) - 1) Next, we define the weights and the biases for the RNN: weight = bias = tf.get_variable("weight", shape=[rnn_size, 2], dtype=tf.float32, initializer=None, regularizer=None, trainable=True, collections=None) bias = tf.get_variable("bias", shape=[2], dtype=tf.float32, initializer=None, regularizer=None, trainable=True, collections=None) The logits output is then defined. It uses both the weight and the bias from the preceding code: logits_out = tf.nn.softmax(tf.matmul(last, weight) + bias) Now we define the losses for each prediction so that later on, they can contribute to the loss function: losses = tf.nn.sparse_softmax_cross_entropy_with_logits_v2(logits=logits_ou t, labels=y_output) We then define the loss function: loss = tf.reduce_mean(losses) We now define the accuracy of each prediction: accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(logits_out, 1), tf.cast(y_output, tf.int64)), tf.float32)) We then create the training_op with RMSPropOptimizer: optimizer = tf.train.RMSPropOptimizer(learning_rate) train_step = optimizer.minimize(loss) Now let's initialize all the variables using the global_variables_initializer() method: init_op = tf.global_variables_initializer() sess.run(init_op) Additionally, we can create some empty lists to keep track of the training loss, testing loss, training accuracy, and the testing accuracy in each epoch: train_loss = [] test_loss = [] train_accuracy = [] test_accuracy = [] Now we are ready to perform the training, so let's get started. The workflow of the training goes as follows: Shuffle the training data Select the training set and calculate generations Run training step for each batch Run loss and accuracy of training Run the evaluation steps. The following codes include all of the aforementioned steps: shuffled_ix = np.random.permutation(np.arange(len(x_train)))    x_train = x_train[shuffled_ix]    y_train = y_train[shuffled_ix]    num_batches = int(len(x_train)/batch_size) + 1    for i in range(num_batches):        min_ix = i * batch_size        max_ix = np.min([len(x_train), ((i+1) * batch_size)])        x_train_batch = x_train[min_ix:max_ix]        y_train_batch = y_train[min_ix:max_ix]        train_dict = {x_data: x_train_batch, y_output: \ y_train_batch, dropout_keep_prob:0.5}        sess.run(train_step, feed_dict=train_dict)        temp_train_loss, temp_train_acc = sess.run([loss,\                         accuracy], feed_dict=train_dict)    train_loss.append(temp_train_loss)    train_accuracy.append(temp_train_acc)    test_dict = {x_data: x_test, y_output: y_test, \ dropout_keep_prob:1.0}    temp_test_loss, temp_test_acc = sess.run([loss, accuracy], \                    feed_dict=test_dict)    test_loss.append(temp_test_loss)    test_accuracy.append(temp_test_acc)    print('Epoch: {}, Test Loss: {:.2}, Test Acc: {:.2}'.format(epoch+1, temp_test_loss, temp_test_acc)) print('\nOverall accuracy on test set (%): {}'.format(np.mean(temp_test_acc)*100.0)) Following is the output of the preceding code: >>> Epoch: 1, Test Loss: 0.68, Test Acc: 0.82 Epoch: 2, Test Loss: 0.68, Test Acc: 0.82 Epoch: 3, Test Loss: 0.67, Test Acc: 0.82 … Epoch: 997, Test Loss: 0.36, Test Acc: 0.96 Epoch: 998, Test Loss: 0.36, Test Acc: 0.96 Epoch: 999, Test Loss: 0.35, Test Acc: 0.96 Epoch: 1000, Test Loss: 0.35, Test Acc: 0.96 Overall accuracy on test set (%): 96.19799256324768 Well done! The accuracy of the RNN is above 96%, which is outstanding. Now let's observe how the loss propagates across each iteration and over time: epoch_seq = np.arange(1, epochs+1) plt.plot(epoch_seq, train_loss, 'k--', label='Train Set') plt.plot(epoch_seq, test_loss, 'r-', label='Test Set') plt.title('RNN training/test loss') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend(loc='upper left') plt.show() Figure 1: a) RNN training and test loss per epoch b) test accuracy per epoch We also plot the accuracy over time: plt.plot(epoch_seq, train_accuracy, 'k--', label='Train Set') plt.plot(epoch_seq, test_accuracy, 'r-', label='Test Set') plt.title('Test accuracy') plt.xlabel('Epochs') plt.ylabel('Accuracy') plt.legend(loc='upper left') plt.show() We discussed the implementation of RNNs in TensorFlow. We saw how to make predictions with data that has a high temporal dependency and how to develop real-life predictive models that make the predictive analytics easier using RNNs. If you want to delve into neural networks and implement deep learning algorithms check out this book, Deep learning with TensorFlow - Second Edition. Top 5 Deep Learning Architectures Understanding Sentiment Analysis and other key NLP concepts Facelifting NLP with Deep Learning
Read more
  • 0
  • 0
  • 6196

article-image-four-ibm-facial-recognition-patents-in-2018-we-found-intriguing
Natasha Mathur
11 Aug 2018
10 min read
Save for later

Four IBM facial recognition patents in 2018, we found intriguing

Natasha Mathur
11 Aug 2018
10 min read
The media has gone into a frenzy over Google’s latest facial recognition patent that shows an algorithm can track you across social media and gather your personal details. We thought, we’d dive further into what other patents Google has applied for in facial recognition tehnology in 2018. What we discovered was an eye opener (pun intended). Google is only the 3rd largest applicant with IBM and Samsung leading the patents race in facial recognition. As of 10th Aug, 2018, 1292 patents have been granted in 2018 on Facial recognition. Of those, IBM received 53. Here is the summary comparison of leading companies in facial recognition patents in 2018. Read Also: Top four Amazon patents in 2018 that use machine learning, AR, and robotics IBM has always been at the forefront of innovation. Let’s go back about a quarter of a century, when IBM invented its first general-purpose computer for business. It built complex software programs that helped in launching Apollo missions, putting the first man on the moon. It’s chess playing computer, Deep Blue, back in 1997,  beat Garry Kasparov, in a traditional chess match (the first time a computer beat a world champion). Its researchers are known for winning Nobel Prizes. Coming back to 2018, IBM unveiled the world’s fastest supercomputer with AI capabilities, and beat the Wall Street expectations by making $20 billion in revenue in Q3 2018 last month, with market capitalization worth $132.14 billion as of August 9, 2018. Its patents are a major part of why it continues to be valuable highly. IBM continues to come up with cutting-edge innovations and to protect these proprietary inventions, it applies for patent grants. United States is the largest consumer market in the world, so patenting the technologies that the companies come out with is a standard way to attain competitive advantage. As per the United States Patent and Trademark Office (USPTO), Patent is an exclusive right to invention and “the right to exclude others from making, using, offering for sale, or selling the invention in the United States or “importing” the invention into the United States”. As always, IBM has applied for patents for a wide spectrum of technologies this year from Artificial Intelligence, Cloud, Blockchain, Cybersecurity, to Quantum Computing. Today we focus on IBM’s patents in facial recognition field in 2018. Four IBM facial recognition innovations patented in 2018 Facial recognition is a technology which identifies and verifies a person from a digital image or a video frame from a video source and IBM seems quite invested in it. Controlling privacy in a face recognition application Date of patent: January 2, 2018 Filed: December 15, 2015 Features: IBM has patented for a face-recognition application titled “Controlling privacy in a face recognition application”. Face recognition technologies can be used on mobile phones and wearable devices which may hamper the user privacy. This happens when a "sensor" mobile user identifies a "target" mobile user without his or her consent. The present mobile device manufacturers don’t provide the privacy mechanisms for addressing this issue. This is the major reason why IBM has patented this technology. Editor’s Note: This looks like an answer to the concerns raised over Google’s recent social media profiling facial recognition patent.   How it works? Controlling privacy in a face recognition application It consists of a privacy control system, which is implemented using a cloud computing node. The system uses a camera to find out information about the people, by using a face recognition service deployed in the cloud. As per the patent application “the face recognition service may have access to a face database, privacy database, and a profile database”. Controlling privacy in a face recognition application The facial database consists of one or more facial signatures of one or more users. The privacy database includes privacy preferences of target users. Privacy preferences will be provided by the target user and stored in the privacy database.The profile database contains information about the target user such as name, age, gender, and location. It works by receiving an input which includes a face recognition query and a digital image of a face. The privacy control system then detects a facial signature from the digital image. The target user associated with the facial signature is identified, and profile of the target user is extracted. It then checks the privacy preferences of the user. If there are no privacy preferences set, then it transmits the profile to the sensor user. But, if there are privacy preferences then the censored profile of the user is generated omitting out the private elements in the profile. There are no announcements, as for now, regarding when this technology will hit the market. Evaluating an impact of a user's content utilized in a social network Date of patent: January 30, 2018 Filed: April 11, 2015 Features:  IBM has patented for an application titled “Evaluating an impact of a user's content utilized in a social network”.  With so much data floating around on social network websites, it is quite common for the content of a document (e.g., e-mail message, a post, a word processing document, a presentation) to be reused, without the knowledge of an original author. Evaluating an impact of a user's content utilised in a social network Evaluating an impact of a user's content utilized in a social network Because of this, the original author of the content may not receive any credit, which creates less motivation for the users to post their original content in a social network. This is why IBM has decided to patent for this application. Evaluating an impact of a user's content utilized in a social network As per the patent application, the method/system/product  “comprises detecting content in a document posted on a social network environment being reused by a second user. The method further comprises identifying an author of the content. The method additionally comprises incrementing a first counter keeping track of a number of times the content has been adopted in derivative works”. There’s a processor, which generates an “impact score” which  represents the author's ability to influence other users to adopt the content. This is based on the number of times the content has been adopted in the derivative works. Also, “the method comprises providing social credit to the author of the content using the impact score”. Editor’s Note: This is particularly interesting to us as IBM, unlike other tech giants, doesn’t own a popular social network or media product. (Google has Google+, Microsoft has LinkedIn, Facebook and Twitter are social, even Amazon has stakes in a media entity in the form of Washington Post). No information is present about when or if this system will be used among social network sites. Spoof detection for facial recognition Date of patent: February 20, 2018 Filed: December 10, 2015 Features: IBM patented an application named “Spoof detection for facial recognition”.  It provides a method to determine whether the image is authentic or not. As per the patent “A facial recognition system is a computer application for automatically identifying or verifying a person from a digital image or a video frame from a video source.” Editor’s Note: This seems to have a direct impact on the work around tackling deepFakes, which incidentally is something DARPA is very keen on. Could IBM be vying for a long term contract with the government? How it works? The patent consists of a system that helps detect “if a face in a facial recognition authentication system is a three-dimensional structure based on multiple selected images from the input video”.                                      Spoof detection for facial recognition There are four or more two-dimensional feature points which are located via an image processing device connected to the camera. Here the two-dimensional feature points do not lie on the same two-dimensional plane. The patent reads that “one or more additional images of the user's face can be received with the camera; and, the at least four two-dimensional feature points can be located on each additional image with the image processor. The image processor can identify displacements between the two-dimensional feature points on the additional image and the two-dimensional feature points on the first image for each additional image” Spoof detection for facial recognition There is also a processor connected to the image processing device that helps figure out whether the displacements conform to a three-dimensional surface model. The processor can then determine whether to authenticate the user depending on whether the displacements conform to the three-dimensional surface model. Facial feature location using symmetry line Date of patent: June 5, 2018 Filed: July 20, 2015 Features: IBM patented for an application titled “Facial feature location using symmetry line”. As per the patent, “In many image processing applications, identifying facial features of the subject may be desired. Currently, location of facial features require a search in four dimensions using local templates that match the target features. Such a search tends to be complex and prone to errors because it has to locate both (x, y) coordinates, scale parameter and rotation parameter”. Facial feature location using symmetry line Facial feature location using symmetry line The application consists of a computer-implemented method that obtains an image of the subject’s face. After that it automatically detects a symmetry line of the face in the image, where the symmetry line intersects at least a mouth region of the face. It then automatically locates a facial feature of the face using the symmetry line. There’s also a computerised apparatus with a processor which performs the steps of obtaining an image of a subject’s face and helps locate the facial feature.  Editor’s note: Atleast, this patent makes direct sense to us. IBM is majorly focusing on bring AI to healthcare. A patent like this can find a lot of use in not just diagnostics and patient care, but also in cutting edge areas like robotics enabled surgeries. IBM is continually working on new technologies to provide the world with groundbreaking innovations. Its big investments in facial recognition technology speaks volumes about how IBM is well-versed with its endless possibilities. With the facial recognition technological progress,  come the privacy fears. But, IBM’s facial recognition application patent has got it covered as it lets the users set privacy preferences. This can be a great benchmark for IBM as no many existing applications are currently doing it. The social credit score evaluating app can really help bring the voice back to the users interested in posting content on social media platforms. The spoof detection application will help maintain authenticity by detecting forged images. Lastly, the facial feature detection can act as a great additional feature for image processing applications. IBM has been heavily investing in facial recognition technology. There are no guarantees by IBM as to whether these patents will ever make it to practical applications, but it does say a lot about how IBM thinks about the technology. Four interesting Amazon patents in 2018 that use machine learning, AR, and robotics Facebook patents its news feed filter tool to provide more relevant news to its users Google’s new facial recognition patent uses your social network to identify you!  
Read more
  • 0
  • 0
  • 24018

article-image-time-series-modeling-what-is-it-why-it-matters-how-its-used
Sunith Shetty
10 Aug 2018
11 min read
Save for later

Time series modeling: What is it, Why it matters and How it's used

Sunith Shetty
10 Aug 2018
11 min read
A series can be defined as a number of events, objects, or people of a similar or related kind coming one after another; if we add the dimension of time, we get a time series. A time series can be defined as a series of data points in time order. In this article, we will understand what time series is and why it is one of the essential characteristics for forecasting. This article is an excerpt from a book written by Harish Gulati titled SAS for Finance. The importance of time series What importance, if any, does time series have and how will it be relevant in the future? These are just a couple of fundamental questions that any user should find answers to before delving further into the subject. Let's try to answer this by posing a question. Have you heard the terms big data, artificial intelligence (AI), and machine learning (ML)? These three terms make learning time series analysis relevant. Big data is primarily about a large amount of data that may be analyzed computationally to reveal patterns, trends, and associations, especially relating to human behavior and interaction. AI is a kind of technology that is being developed by data scientists, computational experts, and others to enable processes to become more intelligent, while ML is an enabler that is helping to implement AI. All three of these terms are interlinked with the data they use, and a lot of this data is time series in its nature. This could be either financial transaction data, the behavior pattern of individuals during various parts of the day, or related to life events that we might experience. An effective mechanism that enables us to capture the data, store it, analyze it, and then build algorithms to predict transactions, behavior (and life events, in this instance) will depend on how big data is utilized and how AI and MI are leveraged. A common perception in the industry is that time series data is used for forecasting only. In practice, time series data is used for: Pattern recognition Forecasting Benchmarking Evaluating the influence of a single factor on the time series Quality control For example, a retailer may identify a pattern in clothing sales every time it gets a celebrity endorsement, or an analyst may decide to use car sales volume data from 2012 to 2017 to set a selling benchmark in units. An analyst might also build a model to quantify the effect of Lehman's crash at the height of the 2008 financial crisis in pushing up the price of gold. Variance in the success of treatments across time periods can also be used to highlight a problem, the tracking of which may enable a hospital to take remedial measures. These are just some of the examples that showcase how time series analysis isn't limited to just forecasting. In this chapter, we will review how the financial industry and others use forecasting, discuss what a good and a bad forecast is, and hope to understand the characteristics of time series data and its associated problems. Forecasting across industries Since one of the primary uses of time series data is forecasting, it's wise that we learn about some of its fundamental properties. To understand what the industry means by forecasting and the steps involved, let's visit a common misconception about the financial industry: only lending activities require forecasting. We need forecasting in order to grant personal loans, mortgages, overdrafts, or simply assess someone's eligibility for a credit card, as the industry uses forecasting to assess a borrower's affordability and their willingness to repay the debt. Even deposit products such as savings accounts, fixed-term savings, and bonds are priced based on some forecasts. How we forecast and the rationale for that methodology is different in borrowing or lending cases, however. All of these areas are related to time series, as we inevitably end up using time series data as part of the overall analysis that drives financial decisions. Let's understand the forecasts involved here a bit better. When we are assessing an individual's lending needs and limits, we are forecasting for a single person yet comparing the individual to a pool of good and bad customers who have been offered similar products. We are also assessing the individual's financial circumstances and behavior through industry-available scoring models or by assessing their past behavior, with the financial provider assessing the lending criteria. In the case of deposit products, as long as the customer is eligible to transact (can open an account and has passed know your customer (KYC), anti-money laundering (AML), and other checks), financial institutions don't perform forecasting at an individual level. However, the behavior of a particular customer is primarily driven by the interest rate offered by the financial institution. The interest rate, in turn, is driven by the forecasts the financial institution has done to assess its overall treasury position. The treasury is the department that manages the central bank's money and has the responsibility of ensuring that all departments are funded, which is generated through lending and attracting deposits at a lower rate than a bank lends. The treasury forecasts its requirements for lending and deposits, while various teams within the treasury adhere to those limits. Therefore, a pricing manager for a deposit product will price the product in such a way that the product will attract enough deposits to meet the forecasted targets shared by the treasury; the pricing manager also has to ensure that those targets aren't overshot by a significant margin, as the treasury only expects to manage a forecasted target. In both lending and deposit decisions, financial institutions do tend to use forecasting. A lot of these forecasts are interlinked, as we saw in the example of the treasury's expectations and the subsequent pricing decision for a deposit product. To decide on its future lending and borrowing positions, the treasury must have used time series data to determine what the potential business appetite for lending and borrowing in the market is and would have assessed that with the current cash flow situation within the relevant teams and institutions. Characteristics of time series data Any time series analysis has to take into account the following factors: Seasonality Trend Outliers and rare events Disruptions and step changes Seasonality Seasonality is a phenomenon that occurs each calendar year. The same behavior can be observed each year. A good forecasting model will be able to incorporate the effect of seasonality in its forecasts. Christmas is a great example of seasonality, where retailers have come to expect higher sales over the festive period. Seasonality can extend into months but is usually only observed over days or weeks. When looking at time series where the periodicity is hours, you may find a seasonality effect for certain hours of the day. Some of the reasons for seasonality include holidays, climate, and changes in social habits. For example, travel companies usually run far fewer services on Christmas Day, citing a lack of demand. During most holidays people love to travel, but this lack of demand on Christmas Day could be attributed to social habits, where people tend to stay at home or have already traveled. Social habit becomes a driving factor in the seasonality of journeys undertaken on Christmas Day. It's easier for the forecaster when a particular seasonal event occurs on a fixed calendar date each year; the issue comes when some popular holidays depend on lunar movements, such as Easter, Diwali, and Eid. These holidays may occur in different weeks or months over the years, which will shift the seasonality effect. Also, if some holidays fall closer to other holiday periods, it may lead to individuals taking extended holidays and travel sales may increase more than expected in such years. The coffee shop near the office may also experience lower sales for a longer period. Changes in the weather can also impact seasonality; for example, a longer, warmer summer may be welcome in the UK, but this would impact retail sales in the autumn as most shoppers wouldn't need to buy a new wardrobe. In hotter countries, sales of air-conditioners would increase substantially compared to the summer months' usual seasonality. Forecasters could offset this unpredictability in seasonality by building in a weather forecast variable. We will explore similar challenges in the chapters ahead. Seasonality shouldn't be confused with a cyclic effect. A cyclic effect is observed over a longer period of generally two years or more. The property sector is often associated with having a cyclic effect, where it has long periods of growth or slowdown before the cycle continues. Trend A trend is merely a long-term direction of observed behavior that is found by plotting data against a time component. A trend may indicate an increase or decrease in behavior. Trends may not even be linear, but a broad movement can be identified by analyzing plotted data. Outliers and rare events Outliers and rare events are terminologies that are often used interchangeably by businesses. These concepts can have a big impact on data, and some sort of outlier treatment is usually applied to data before it is used for modeling. It is almost impossible to predict an outlier or rare event but they do affect a trend. An example of an outlier could be a customer walking into a branch to deposit an amount that is 100 times the daily average of that branch. In this case, the forecaster wouldn't expect that trend to continue. Disruptions Disruptions and step changes are becoming more common in time series data. One reason for this is the abundance of available data and the growing ability to store and analyze it. Disruptions could include instances when a business hasn't been able to trade as normal. Flooding at the local pub may lead to reduced sales for a few days, for example. While analyzing daily sales across a pub chain, an analyst may have to make note of a disruptive event and its impact on the chain's revenue. Step changes are also more common now due to technological shifts, mergers and acquisitions, and business process re-engineering. When two companies announce a merger, they often try to sync their data. They might have been selling x and y quantities individually, but after the merger will expect to sell x + y + c (where c is the positive or negative effect of the merger). Over time, when someone plots sales data in this case, they will probably spot a step change in sales that happened around the time of the merger, as shown in the following screenshot: In the trend graph, we can see that online travel bookings are increasing. In the step change and disruptions chart, we can see that Q1 of 2012 saw a substantive increase in bookings, where Q1 of 2014 saw a substantive dip. The increase was due to the merger of two companies that took place in Q1 of 2012. The decrease in Q1 of 2014 was attributed to prolonged snow storms in Europe and the ash cloud disruption from volcanic activity over Iceland. While online bookings kept increasing after the step change, the disruption caused by the snow storm and ash cloud only had an effect on sales in Q1 of 2014. In this case, the modeler will have to treat the merger and the disruption differently while using them in the forecast, as disruption could be disregarded as an outlier and treated accordingly. Also note that the seasonality chart shows that Q4 of each year sees almost a 20% increase in travel bookings, and this pattern continues each calendar year. In this article, we defined time series and learned why it is important for forecasting. We also looked at the characteristics of time series data. To know more how to leverage the analytical power of SAS to perform financial analysis efficiently, you can check out the book SAS for Finance. Read more Getting to know SQL Server options for disaster recovery Implementing a simple Time Series Data Analysis in R Training RNNs for Time Series Forecasting
Read more
  • 0
  • 0
  • 35859
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-send-email-notifications-using-sendgrid
Packt Editorial Staff
10 Aug 2018
6 min read
Save for later

How to send email Notifications using SendGrid

Packt Editorial Staff
10 Aug 2018
6 min read
SendGrid is one of the popular services that allow the audience to send emails for different purposes. In today’s tutorial we will explore to: Create SendGrid account Generate SendGrid API Key Configure SendGrid API key with Azure function app Send an email notification to the website administrator Here, we will learn how to create a SendGrid output binding and send an email notification to the administrator with a static content. In general there would be only administrators so we will be hard coding the email address of the administrator in the To address field of the SendGrid output binding Getting ready Create a SendGrid account API Key from the Azure Management Portal. Generate an API Key from the SendGrid Portal. Create a SendGrid account Navigate to Azure Management Portal and create a SendGrid Email Delivery account by searching for the same in the Marketplace shown as follows: In the SendGrid Email Delivery blade, click on Create button to navigate to the Create a new SendGrid Account. Please select Free tier in the Pricing tier and provide all other details and click on the Create button shown as follows: Once the account is created successfully, navigate to the SendGrid account. You can use the search box available in the top which is shown as follows: Navigate to the Settings, choose configurations and grab the username and SmtpServer from the Configurations blade. Generate SendGrid API key In order to utilize SendGrid account by the Azure Functions runtime, we need to provide the SendGrid API key as input to the Azure Functions. You can generate an API Key from the SendGrid portal. Let's navigate to the SendGrid portal by clicking on the Manage button in the Essentials blade of the SendGrid account shown as follows: In the SendGrid portal, click on the API Keys under Settings section of the Left hand side menu shown as follows: In the API Keys page, click on Create API Key shown as follows: In the Create API Key popup, provide a name and choose the API Key Permissions and click on Create & View button. After a moment you will be able to see the API key. Click on the key to copy the same to the clipboard: Configure SendGrid API key with Azure Function app Create a new app setting in the Azure Function app by navigating to the Application Settings blade under the Platform features section of the function app shown as follows: Click on Save button after adding the app settings in the preceding step. How to do it... Navigate to the Integrate tab of the RegisterUser function and click on New Output button to add a new output binding. Choose the SendGrid output binding and click on Select button to add the binding. Please provide the following parameters in the SendGrid output binding: Message parameter name - leave the default value - message. We will be using this parameter in the run method in a moment. SendGrid API key: Please provide the app settings key that you have created in the application settings. To address: Please provide the email address of the administrator. From address: Please provide the email address from where you would like to send the email. In general, it would be kind of donotreply@example.com. Message subject: Please provide the subject that you would like to have in the email subject. Message Text: Please provide the email body text that you would like to have in the email body. Below is how the SendGrid output binding should look like after providing all the fields: Once you review the values, click on Save to save the changes. Navigate to Run method and make the following changes: Add a new reference for SendGrid and also the namespace Add a new out parameter message of type Mail. Create an object of type Mail. Following is the complete code of the Run method: #r  "Microsoft.WindowsAzure.Storage" #r "SendGrid" using  System.Net; using SendGrid.Helpers.Mail; using  Microsoft.WindowsAzure.Storage.Table; using  Newtonsoft.Json; public  static  void  Run(HttpRequestMessage  req, TraceWriter  log, CloudTable  objUserProfileTable, out  string  objUserProfileQueueItem, out Mail message ) { var  inputs  =  req.Content.ReadAsStringAsync().Result; dynamic  inputJson  =  JsonConvert.DeserializeObject<dynamic>(inputs); string  firstname=  inputJson.firstname; string  lastname=inputJson.lastname; string  profilePicUrl  =  inputJson.ProfilePicUrl; objUserProfileQueueItem  =  profilePicUrl; UserProfile  objUserProfile  =  new  UserProfile(firstname,  lastname); TableOperation  objTblOperationInsert  = TableOperation.Insert(objUserProfile); objUserProfileTable.Execute(objTblOperationInsert); message = new Mail(); } public  class  UserProfile  :  TableEntity { public  UserProfile(string  lastName,  string  firstname,string profilePicUrl) { this.PartitionKey  =  "p1"; this.RowKey  =  Guid.NewGuid().ToString();; this.FirstName  =  firstName; this.LastName  =  lastName; this.ProfilePicUrl  =  profilePicUrl; } public  UserProfile()  {  } public  string  FirstName  {  get;  set;  } public  string  LastName  {  get;  set;  } public  string  ProfilePicUrl  {get;  set;} } Now, let's test the functionality of sending the email by navigating to the RegisterUser function and submit a request with the some test values: { "firstname": "Bill", "lastname": "Gates", "ProfilePicUrl":"https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/ Bill_Gates_June_2015.jpg/220px-Bill_Gates_June_2015.jpg" } How it works... The aim here is to send a notification via email to an administrator updating that a new registration got created successfully. We have used the one of the Azure Function experimental templates named SendGrid as a SMTP server for sending the emails by hard coding the following properties in the SendGrid output bindings: From email address To email address Subject of the email Body of the email SendGrid output bindings will use the API key provided in the app settings to invoke the required APIs of the SendGrid library for sending the emails. To summarize, we learnt about sending an email notification using SendGrid service. [box type="shadow" align="" class="" width=""]This article is an excerpt from the book, Azure Serverless Computing Cookbook, written by Praveen Kumar Sriram. It contains over 50 recipes to help you build applications hosted on Serverless architecture using Azure Functions.[/box] 5 reasons why your business should adopt cloud computing Alibaba Cloud partners with SAP to provide a versatile, one-stop cloud computing environment Top 10 IT certifications for cloud and networking professionals in 2018    
Read more
  • 0
  • 0
  • 18175

article-image-visualizing-data-r-and-python-using-anaconda
Natasha Mathur
09 Aug 2018
7 min read
Save for later

Visualizing data in R and Python using Anaconda [Tutorial]

Natasha Mathur
09 Aug 2018
7 min read
It is said that a picture is worth a thousand words. Through various pictures and graphical presentations, we can express many abstract concepts, theories, data patterns, or certain ideas much clearer. Data can be messy at times, and simply showing the data points would confuse audiences further. If we could have a simple graph to show its main characteristics, properties, or patterns, it would help greatly. In this tutorial, we explain why we should care about data visualization and then we will discuss techniques used for data visualization in R and Python. This article is an excerpt from a book 'Hands-On Data Science with Anaconda' written by Dr. Yuxing Yan, James Yan. Data visualization in R Firstly, let's see the simplest graph for R. With the following one-line R code, we draw a cosine function from -2π to 2π: > plot(cos,-2*pi,2*pi) The related graph is shown here: Histograms could also help us understand the distribution of data points. The previous graph is a simple example of this. First, we generate a set of random numbers drawn from a standard normal distribution. For the purposes of illustration, the first line of set.seed() is actually redundant. Its existence would guarantee that all users would get the same set of random numbers if the same seed was used ( 333 in this case). In other words, with the same set of input values, our histogram would look the same. In the next line, the rnorm(n) function draws n random numbers from a standard normal distribution. The last line then has the hist() function to generate a histogram: > set.seed(333) > data<-rnorm(5000) > hist(data) The associated histogram is shown here: Note that the code of rnorm(5000) is the same as rnorm(5000,mean=0,sd=1), which implies that the default value of the mean is 0 and the default value for sd is 1. The next R program would shade the left-tail for a standard normal distribution: x<-seq(-3,3,length=100) y<-dnorm(x,mean=0,sd=1) title<-"Area under standard normal dist & x less than -2.33" yLabel<-"standard normal distribution" xLabel<-"x value" plot(x,y,type="l",lwd=3,col="black",main=title,xlab=xLabel,ylab=yLabel) x<-seq(-3,-2.33,length=100) y<-dnorm(x,mean=0,sd=1) polygon(c(-4,x,-2.33),c(0,y,0),col="red") The related graph is shown here: Note that according to the last line in the preceding graph, the shaded area is red. In terms of exploring the properties of various datasets, the R package called rattle is quite useful. If the rattle package is not preinstalled, we could run the following code to install it: > install.packages("rattle") Then, we run the following code to launch it; > library(rattle) > rattle() After hitting the Enter key, we can see the following: As our first step, we need to import certain datasets. For the sources of data, we choose from seven potential formats, such as File, ARFF, ODBC, R Dataset, and RData File, and we can load our data from there. The simplest way is using the Library option, which would list all the embedded datasets in the rattle package. After clicking Library, we can see a list of embedded datasets. Assume that we choose acme:boot:Monthly Excess Returns after clicking Execute in the top left. We would then see the following: Now, we can study the properties of the dataset. After clicking Explore, we can use various graphs to view our dataset. Assume that we choose Distribution and select the Benford check box. We can then refer to the following screenshot for more details: After clicking Execute, the following would pop up. The top red line shows the frequencies for the Benford Law for each digits of 1 to 9, while the blue line at the bottom shows the properties of our data set. Note that if you don't have the reshape package already installed in your system, then this either won't run or will ask for permission to install the package to your computer: The dramatic difference between those two lines indicates that our data does not follow a distribution suggested by the Benford Law. In our real world, we know that many people, events, and economic activities are interconnected, and it would be a great idea to use various graphs to show such a multi-node, interconnected picture. If the qgraph package is not preinstalled, users have to run the following to install it: > install.packages("qgraph") The next program shows the connection from a to b, a to c, and the like: library(qgraph) stocks<-c("IBM","MSFT","WMT") x<-rep(stocks, each = 3) y<-rep(stocks, 3) correlation<-c(0,10,3,10,0,3,3,3,0) data <- as.matrix(data.frame(from =x, to =y, width =correlation)) qgraph(data, mode = "direct", edge.color = rainbow(9)) If the data is shown, the meaning of the program will be much clearer. The correlation shows how strongly those stocks are connected. Note that all those values are randomly chosen with no real-world meanings: > data from to width [1,] "IBM" "IBM" " 0" [2,] "IBM" "MSFT" "10" [3,] "IBM" "WMT" " 3" [4,] "MSFT" "IBM" "10" [5,] "MSFT" "MSFT" " 0" [6,] "MSFT" "WMT" " 3" [7,] "WMT" "IBM" " 3" [8,] "WMT" "MSFT" " 3" [9,] "WMT" "WMT" " 0" A high value for the third variable suggests a stronger correlation. For example, IBM is more strongly correlated with MSFT, with a value of 10, than its correlation with WMT, with a value of 3. The following graph shows how strongly those three stocks are correlated: The following program shows the relationship or interconnection between five factors: library(qgraph) data(big5) data(big5groups) title("Correlations among 5 factors",line = 2.5) qgraph(cor(big5),minimum = 0.25,cut = 0.4,vsize = 1.5, groups = big5groups,legend = TRUE, borders = FALSE,theme = 'gray') The related graph is shown here: Data visualization in Python The most widely used Python package for graphs and images is called matplotlib. The following program can be viewed as the simplest Python program to generate a graph since it has just three lines: import matplotlib.pyplot as plt plt.plot([2,3,8,12]) plt.show() The first command line would upload a Python package called matplotlib.pyplot and rename it to plt. Note that we could even use other short names, but it is conventional to use plt for the matplotlib package. The second line plots four points, while the last one concludes the whole process. The completed graph is shown here: For the next example, we add labels for both x and y, and a title. The function is the cosine function with an input value varying from -2π to 2π: import scipy as sp import matplotlib.pyplot as plt x=sp.linspace(-2*sp.pi,2*sp.pi,200,endpoint=True) y=sp.cos(x) plt.plot(x,y) plt.xlabel("x-value") plt.ylabel("Cosine function") plt.title("Cosine curve from -2pi to 2pi") plt.show() The nice-looking cosine graph is shown here: If we received $100 today, it would be more valuable than what would be received in two years. This concept is called the time value of money, since we could deposit $100 today in a bank to earn interest. The following Python program uses size to illustrate this concept: import matplotlib.pyplot as plt fig = plt.figure(facecolor='white') dd = plt.axes(frameon=False) dd.set_frame_on(False) dd.get_xaxis().tick_bottom() dd.axes.get_yaxis().set_visible(False) x=range(0,11,2) x1=range(len(x),0,-1) y = [0]*len(x); plt.annotate("$100 received today",xy=(0,0),xytext=(2,0.15),arrowprops=dict(facecolor='black',shrink=2)) plt.annotate("$100 received in 2 years",xy=(2,0),xytext=(3.5,0.10),arrowprops=dict(facecolor='black',shrink=2)) s = [50*2.5**n for n in x1]; plt.title("Time value of money ") plt.xlabel("Time (number of years)") plt.scatter(x,y,s=s); plt.show() The associated graph is shown here. Again, the different sizes show their present values in relative terms: To summarize, we discussed ways data visualization works in Python and R.  Visual presentations can help our audience understand data better. If you found this post useful, check out the book 'Hands-On Data Science with Anaconda' to learn about different types of visual representation written in languages such as R, Python, Julia, etc. A tale of two tools: Tableau and Power BI Anaconda Enterprise version 5.1.1 released! 10 reasons why data scientists love Jupyter notebooks
Read more
  • 0
  • 0
  • 52606

article-image-apple-joins-the-thread-group-signaling-its-smart-home-ambitions-with-homekit-siri-and-other-iot-products
Bhagyashree R
09 Aug 2018
3 min read
Save for later

Apple joins the Thread Group, signaling its Smart Home ambitions with HomeKit, Siri and other IoT products

Bhagyashree R
09 Aug 2018
3 min read
Apple is now a part of the Thread Group’s list of members, alongside its top rivals - Nest (a subsidiary of Google) and Amazon. This indicates some advancements in their HomeKit software framework and inter-device communication between iOS devices. Who is the Thread Group? The Thread Group is a non-profit company who have developed the network protocol Thread, with the aim of being the best way to connect and control IoT products. These are the features that enable them to do so: Mesh networking: It uses mesh network design, connecting hundreds of products securely and reliably, which also means no single point of failure. Secure: It provides security at network and application layers. To ensure only authorized devices join the network, it uses product install codes. They use AES encryption to close security holes that exist in other wireless protocols and smartphone-era authentication scheme. Battery friendly: Based on the power efficient IEEE 802.15.4 MAC/PHY, it ensures extremely low power consumption. Short messaging, streamlined routing protocol, use of low power wireless system-on-chips also makes it battery friendly. Based on IPv6: It is interoperable by design using proven, open standards and IPv6 technology with 6LoWPAN (short for, IPv6 over Low-Power Wireless Personal Area Networks) as the foundation. 6LoWPAN is an IPv6 based low-power wireless personal area network which is comprises of devices that conform to the IEEE 802.15.4-2003 standard Scalable: It can scale upto 250+ devices into a single network supporting multiple hops. What this membership brings to Apple? The company has not revealed their plans yet, but nothing is stopping us from imagining what they possibly could do with Thread. According to a redditor, the following are some potential use of Thread by Apple HomeKit by Apple uses WiFi and Bluetooth as its wireless protocols. WiFi is very power hungry and Bluetooth is short-ranged. With Thread’s mesh network and power-efficient design this problem could be solved. Apple only allows certain products to operate on battery, requiring others to be plugged into power constantly, HomeKit cameras, for instance. Critical to both Apple and extended-use home devices, Thread promises “extremely low power consumption.” Apple could have plans to provide support for the number of IoT smart home devices the HomePod is capable of connecting to with Thread. With the support of Thread, iOS devices could guarantee better inter-device Siri communications, more reliable continuity features, and secure geo-fencing. Apple joining the group could mean that it may become open to more hardware when it comes to its HomeKit and also become reasonable from a cost perspective in the smart home area. Apple releases iOS 12 beta 2 with screen time and battery usage updates among others macOS Mojave: Apple updates the Mac experience for 2018 Apple stocks soar just shy of $1 Trillion market cap as revenue hits $53.3 Billion in Q3 earnings 2018
Read more
  • 0
  • 0
  • 20585

article-image-why-golan-is-the-fastest-growing-language-on-github
Sugandha Lahoti
09 Aug 2018
4 min read
Save for later

Why Golang is the fastest growing language on GitHub

Sugandha Lahoti
09 Aug 2018
4 min read
Google’s Go language or alternatively Golang is currently one of the fastest growing programming languages in the software industry. Its speed, simplicity, and reliability make it the perfect choice for all kinds of developers. Now, its popularity has further gained momentum. According to a report, Go is the fastest growing language on GitHub in Q2 of 2018. Go has grown almost 7% overall with a 1.5% change from the previous Quarter. Source: Madnight.github.io What makes Golang so popular? A person was quoted on Reddit saying, “What I would have done in Python, Ruby, C, C# or C++, I'm now doing in Go.” Such is the impact of Go. Let’s see what makes Golang so popular. Go is cross-platform, so you can target an operating system of your choice when compiling a piece of code. Go offers a native concurrency model that is unlike most mainstream programming languages. Go relies on a concurrency model called CSP ( Communicating Sequential Processes). Instead of locking variables to share memory, Golang allows you to communicate the value stored in your variable from one thread to another. Go has a fairly mature package of its own. Once you install Go, you can build production level software that can cover a wide range of use cases from Restful web APIs to encryption software, before needing to consider any third party packages. Go code typically compiles to a single native binary, which basically makes deploying an application written in Go as easy as copying the application file to the destination server. Go is also being rapidly being adopted as the go-to cloud native language and by leading projects like Docker and Ethereum. It’s concurrency feature and easy deployment make it a popular choice for cloud development. Can Golang replace Python? Reddit is abuzz with people sharing their thoughts about whether Golang would replace Python. A user commented that “Writing a utility script is quicker in Go than in Python or JS. Not quicker as in performance, but in terms of raw development speed.” Another Reddit user pointed out three reasons not to use Python in a Reddit discussion, Why are people ditching python for go?: Dynamic compilation of Python can result in errors that exist in code, but they are in fact not detected. CPython really is very slow; very specifically, procedures that are invoked multiple times are not optimized to run more quickly in future runs (like pypy); they always run at the same slow speed. Python has a terrible distribution story; it's really hard to ship all your Python dependencies onto a new system. Go addresses those points pretty sharply. It has a good distribution story with static binaries. It has a repeatable build process, and it's pretty fast. In the same discussion, however, a user nicely sums it up saying, “There is nothing wrong with python except maybe that it is not statically typed and can be a bit slow, which also depends on the use case. Go is the new kid on the block, and while Go is nice, it doesn't have nearly as many libraries as python does. When it comes to stable, mature third-party packages, it can't beat python at the moment.” If you’re still thinking about whether or not to begin coding with Go, here’s a quirky rendition of the popular song Let it Go from Disney’s Frozen to inspire you. Write in Go! Write in Go! Go Cloud is Google’s bid to establish Golang as the go-to language of cloud Writing test functions in Golang [Tutorial] How Concurrency and Parallelism works in Golang [Tutorial]
Read more
  • 0
  • 0
  • 56943
article-image-share-projects-and-environment-on-anaconda
Natasha Mathur
09 Aug 2018
7 min read
Save for later

Share projects and environment on Anaconda cloud [Tutorial]

Natasha Mathur
09 Aug 2018
7 min read
When a small group of developers works on a same project, there is a need to share programs, command datasets, and working environments, and Anaconda Cloud could be used for this.  Usually, we can save our data on other people's servers. For Anaconda Cloud, users can use the platform to save and share packages, notebooks, projects, and environments. The public projects and notebooks are free. At the moment, private plans start at $7 per month. Anaconda Cloud allows users to create or distribute software packages. In this article, we will learn about Anaconda cloud and how to share projects and environment on Anaconda. This article is an excerpt from a book 'Hands-On Data Science with Anaconda' written by Dr. Yuxing Yan, James Yan. So, let's get started! Firstly, for a Windows version of Anaconda, click All Programs | Anaconda, and then choose Anaconda Cloud. After double-clicking on Cloud, the welcome screen will appear. Based on the information presented by the welcome screen, we know that we need an account with Anaconda before we can use it. After login, we will see the following screen: For example, if you double-click on Installing your first package, you will get more information on Anaconda Cloud. We do not need to be logged in, or even need a cloud account, to search for public packages, download, and install them. We need an account only to access private packages without a token or to share your packages with others. For Anaconda Cloud, users can use the platform to save and share projects and environments. Sharing projects in Anaconda First, let's look at the definition of a project. A project is a folder that contains an anaconda-project.yml configuration file together with scripts (code), notebooks, datasets, and other files. We can add a folder into a project by adding a configuration file named anaconda-project.yml to the folder. The configuration file can include the following sections: commands, variables, services, downloads, packages, channels, and environment specifications. Data scientists can use projects to encapsulate data science projects and make them easily portable. A project is usually compressed into a .tar.bz2 file for sharing and storing. Anaconda Project automates setup steps so that people with whom you share projects can run your projects with the following single command: anaconda-project run To install Anaconda Project, type the following: conda install anaconda-project Anaconda Project encapsulates data science projects and makes them easily portable. It automates setup steps such as installing the right packages, downloading files, setting environment variables, and running commands. Project makes it easy to reproduce your work, share projects with others, and run them on different platforms. It also simplifies deployment to servers. Anaconda projects run the same way on your machine, on another user's machine, or when deployed to a server. Traditional build scripts such as setup.py automate the building of the project – going from source code to something runnable – while Project automates running the project, taking build artifacts, and doing any necessary setup before executing them. We can use Project on Windows, macOS, and Linux. Project is supported and offered by Anaconda Inc® and contributors under a three-clause BSD license. Project sharing will save us a great deal of time since other developers will not spend too much time on the work done already. Here is the procedure: Build up your project Log in to Anaconda From the project's directory on your computer, type the following command: anaconda-project upload Alternatively, from Anaconda Navigator, in the Projects tab, upload via the bottom-right Upload to Anaconda Cloud. Projects can be any directory of code and assets. Often, projects will contain notebooks or Bokeh applications, for example. Here, we show how to generate a project called project01. First, we want to move to the correct location. Assume that we choose c:/temp/. The key command is given here: anaconda-project init --directory project01 Next, both commands are shown side by side as well: $ cd c:/temp/ $ anaconda-project init --directory project01 Create directory 'c:tempproject01'? y Project configuration is in c:tempproject01iris/anaconda-project.yml The corresponding output is shown here: We can also turn any existing directory into a project by switching to the directory and then running anaconda-project init without options or arguments. We can use MS Word to open anaconda-project.yml (see the first couple of lines shown here): # This is an Anaconda project file. # # Here you can describe your project and how to run it. # Use `anaconda-project run` to run the project. # The file is in YAML format, please see http://www.yaml.org/start.html for more. # # Set the 'name' key to name your project # name: project01 # # Set the 'icon' key to give your project an icon # icon: # # Set a one-sentence-or-so 'description' key with project details # description: # # In the commands section, list your runnable scripts, notebooks, and other code. # Use `anaconda-project add-command` to add commands. # There are two ways to share our projects with others. First, we archive the project by issuing the following command: anaconda-project archive project01.zip Then, we email the ZIP file to our colleague or others. The second way of sharing a project is to use Anaconda Cloud. Log in to Anaconda Cloud first. From the project's directory on our computer, type anaconda-project upload, or, from Anaconda Navigator, in the Projects tab, upload via the bottom-right Upload to Anaconda Cloud. Now that we're done looking at how you can share projects. Let's find out how you can share environments with your partner. Sharing of environments In terms of computer software, an operating environment or integrated applications environment is the environment in which users can execute software. Usually, such an environment consists of a user interface and an API. To a certain degree, the term platform could be viewed as its synonym. There are many reasons why we want to share our environment with someone else. For example, they can re-create a test that we have done. To allow them to quickly reproduce our environment with all of its packages and versions, give them a copy of your environment.yml file. Depending on the operating system, we have the following methods to export our environment file. Note that if we already have an environment.yml file in our current directory, it will be overwritten during this task. There are different ways to activate the myenv environment file depending on the systems used. For Windows users, in our Anaconda prompt, type the following command: activate myenv On macOS and Linux, in our Terminal window, issue the following command: source activate myenv Note that we replace myenv with the name of the environment. To export our active environment to a new file, type the following: conda env export > environment.yml To share, we can simply email or copy the exported environment.yml file to the other person. On the other hand, in order to remove an environment, run the following code in our Terminal window or at an Anaconda prompt: conda remove --name myenv --all Alternatively, we can specify the name, as shown here: conda env remove --name myenv To verify that the environment was removed, run the following command line: conda info --envs In this tutorial, we discussed Anaconda Cloud. Some topics included how to share different projects over different platforms and how to share your working environments. If you found this post useful, be sure to check out the book 'Hands-On Data Science with Anaconda' to learn further about replicating others' environments locally, and downloading a package from Anaconda. Anaconda 5.2 releases! Anaconda Enterprise version 5.1.1 released! 10 reasons why data scientists love Jupyter notebooks
Read more
  • 0
  • 0
  • 15759

article-image-create-unity-character-animations-and-avatars
Amarabha Banerjee
08 Aug 2018
10 min read
Save for later

Creating interactive Unity character animations and avatars [Tutorial]

Amarabha Banerjee
08 Aug 2018
10 min read
The early Unity versions' Legacy Animation System is used in Unity for a wide range of things, such as animating the color of a light or other simple animations on 3D objects in a scene, as well as animating skinned characters for certain kinds of games. In this tutorial, we will look at the basic settings for the Legacy Animation System. Then, we will step into the new animation system, gaining an understanding of the ThirdPersonCharacter prefab, and looking at the difference between the in-place and Root Motion animation methods available within Animator. If you want to dive deep into developing cutting-edge modern day Unity 2D games then this piece is for you. We will deal with character animations using Unity today. This article is an excerpt from the book Unity 2017 Game Development Essentials written by Tommaso Lintrami.  Importing character models and animations To import a model rig or an animation, just drag the model file to the Assets folder of your project. When you select the file in the Project view, you can edit the Import Settings in the Inspector panel: Please refer to the updated Unity online manual for a full description of the available import options: https://docs.unity3d.com/Manual/FBXImporter-Model.html. Importing animations using multiple model files The common way to import animations in Unity is to follow a naming convention scheme that is recognized automatically. You basically create, or ask the artist to create, separate model files and name them with the modelName@animationName.fbx convention. For example, for a model called Warrior_legacy, you could import separate idle, walk, jump, and attack animations using files named Warrior_legacy@idle.fbx, Warrior_legacy@jump.fbx, Warrior_legacy@standard_run_inPlace.fbx, and Warrior_legacy@walking_inPlace.fbx. Only the animation data from these files will be used, even if the original files are exported with mesh data from the animation software package: In the editor's Project view, the .fbx suffix is not shown in the preview, but can still be seen in the bottom line of the view. Unity automatically imports all the files, collects all the animation clips from them, and associates them with the file without the @ symbol. In the example above, the Warrior_legacy.fbx file will be set up to reference offensive_idle, jumping, running_inPlace, and sword_and_shield_walk_inPlace. To export the base rig, simply export a model file from your favorite digital content creation package with no animations ticked in the FBX exporter (for example, Warrior_legacy.fbx)  and the four animation clips as Warrior_legacy@animname.fbx by exporting the desired keyframes for each one of them (enabling animation in the graphic package's FBX export dialog). When imported in Unity, we will select the main rig file ( Warrior_legacy.fbx) and set its Rig type to Legacy: Setting up the animation We need to instruct Unity on how we want to play these animation clips, for instance, we certainly want the walk, idle, and running animation clips to play in a loop, while the jump and the attack animation clips should play in a single shot. Choose the Idle animation clip in the Project view folder where the legacy animation resides and then switch to the Animations tab in the Inspector: Set the Wrap Mode to PingPong in both the top and bottom parts of the panel, as shown in the preceding image. In many cases, you might also want to create an additional in-between loop frame, checking the Add Loop Frame option. This is needed to avoid an ugly animation loop being performed because the first and last frame of the animation are too different from each other. Click on the Apply button at the bottom of the panel to apply the changes. This will be required if the first and last frames of the animation are much different and require an additional frame in-between to interpolate between the two in order to obtain a good loop for this Animation Clip. Now, drag the Warrior_legacy.fbx main file into the scene. You should see a new GameObject with an Animations component attached, with all the reference clips already set up, and with the first specified to play at start when the Play On Awake checkbox is selected in the component (default). You can look at the final result for this part in the Chapter5_legacy Unity scene in the book's code project folder. Building the Player with Animator The Animator component was introduced in Unity 4 to replace the older Legacy Animation System. If you are completely new to Unity, you should start directly with the new animation system and consider the old one as still being good for many things, not only related to character animation. Animator introduced many cool things that were only partially available (and only through coding) with the old animation system. In the code folder, under Chapter 5-6-7/Models/Characters, you will find three folders for the warrior model rig. One is meant for the old Legacy Animation component, and the other two are for use with the Animator. The new system is made by a new animation component, the Animator, a powerful state-machine that controls the whole animation process and the Avatar configuration system. The Animator component will be mapped to a corresponding avatar and to an Animator Controller asset file, which can be created, like other files, from the Project view and edited in the Animator window. What is an avatar in Unity? When an .fbx 3D model file with a skeleton made of joints/bones is imported in Unity, if you expand the file in the Project view, you will see, among the various parts of it, an avatar's icon. The following screenshot represents the Warrior_Final.fbx rigged model automatically created by the Warrior_FinalAvatar component: When importing a rigged model instead (an FBX model with a skeleton or bones and, optionally, animations), Unity will configure it automatically for a Generic avatar. A Generic avatar is meant for any kind of non-human character rig, such as animals, non-biped monsters, plants, and so on. Typically, for your biped/humanoid characters, you want to switch the default import flag for the Rig Animation Type to Humanoid: This term comes from the Latin word bi (two) and ped (foot); this 3D animation-specific term indicates an anthropomorphic/humanoid character standing and walking on two legs. This name was introduced into 3D animation by 3D Studio Max, where Biped was the term for Character Studio to manage a rigged human character and its animations. As the default import setting for the Rig is Generic, we will switch to Humanoid for all the .fbx files in the Warrior_Mecanim_InPlace folder with the only exclusion being the non-rigged Warrior_final_non-rigged.fbx sample model mentioned earlier. Configuring an avatar Now, hit the Configure button and the actual scene and the Inspector will be temporarily replaced with the avatar, (as in the following screenshot), until the Done button is clicked and the editor returns to the previously loaded scene. Because the model included in the book codes is already a Mecanim-ready rig, you can just click on the Done button. On the left, the Scene view switched temporary for showing Avatar configuration results and the Inspector on the right showing configuration options. Most of the time, and in this case, you will not set the mapping for hands, fingers, and eyes separately, so the first of the four tabs (Body, Head, Left Arm, and Right Arm) will be enough for our purpose. The head is usually mapped for independent eyeball movement and/or jaw movement to allow a basic character speech movement whenever your game needs any of these features. The head part of the avatar configuration Inspector panel is shown as follows: A quick note on lip sync. Lip sync is an advanced technique, where a 3D character's face will change and animate its mouth and eyes when a certain audio file is playing. Unity doesn't support lip sync out of the box, but it can be done in many ways with external libraries and an appropriate model rig. Since Unity 4.5 onward, animation Blend Shapes are supported, allowing facial muscles' gestures to be embedded in the .fbx model and used in real time by the application. This technique is more modern than standard lip sync for game character's speeches; in both cases, a library or a discreet amount of coding would be needed to make the character speak correctly when the corresponding audio file is played. Hands mapping will be used only when your characters need fine finger movements hence will not be covered. The best scenario for this is a game where characters perform a lot of specific actions with many different tools (guns, hammers, knives, hacking, or maybe just making gestures while talking during a cinematic cut scene). Another example would be an avatar for virtual reality, where the Leap Motion, Data Gloves, or similar devices are used to track the hands of users with the 3 phalanges of their 10 fingers. If the rig you are importing is not Mecanim-ready, this is the place to map your bones to the appropriate spots on the green diagram in the Inspector, which is subdivided into body, head, left hand, and right hand. To configure an Avatar from a model that was not rigged following Mecanim's skeleton rules, we have the following two options: Using the auto-mapping feature available, which will try to automatically map the bones for you Manually map the bones of your model to the corresponding spots on the diagram The avatar configuration Inspector panel shows the skeleton's main bones mapped to the avatar: The Automap feature, accessible from the drop-down menu at the bottom-left part of the avatar Inspector, can automatically assign the bones of your models to the correct ones for a mecanim rig. This is mainly performed by reading bone names and analyzing the structure of the skeleton, and it is not 100% rig proof. So, you might need some tweaking (manual mapping) of your custom character models. As you can see, there are also Load and Save options to store this mapping. This is useful if you have a whole bunch of rigged character models all done with the same skeleton naming convention. The Clear option will clear up all the current bone mapping. The Pose drop-down menu is needed only if you want to enforce the T-pose, or sample the actual pose, and is rarely needed, but can help fix eventual modeler/3D artist mistakes or to make variations of an avatar. We discussed about creating Unity Character animations and how it will help you build interactive games with unity. Check out the book Unity 2017 Game Development Essentials for hands on game development in Unity 2017. Unite Berlin 2018 Keynote: Unity partners with Google, launches Ml-Agents ToolKit 0.4, Project MARS AI for Unity game developers: How to emulate real-world senses in your NPC agent Working with Unity Variables to script powerful Unity 2017 games
Read more
  • 0
  • 0
  • 28726

article-image-diffractive-deep-neural-network-d2nn-ucla-developed-ai-device-can-identify-objects-at-the-speed-of-light
Bhagyashree R
08 Aug 2018
3 min read
Save for later

Diffractive Deep Neural Network (D2NN): UCLA-developed AI device can identify objects at the speed of light

Bhagyashree R
08 Aug 2018
3 min read
Researchers at the University of California, Los Angeles (UCLA) have developed a 3D-printed all-optical deep learning architecture called Diffractive Deep Neural Network (D2NN). D2NN is a deep learning neural network physically formed by multiple layers of diffractive surfaces that work in collaboration to optically perform an arbitrary function. While the inference/prediction of the physical network is all-optical, the learning part that leads to its design is done through a computer. How does D2NN work? A computer-simulated design was created first, then the researchers with the help of a 3D printer created very thin polymer wafers. The uneven surface of the wafers helped diffract light coming from the object in different directions. The layers are composed of tens of thousands of artificial neurons or tiny pixels from which the light travels through. These layers together, form an “optical network” that shapes how incoming light travels through them. The network is able to identify an object because the light coming from the object is diffracted mostly toward a single pixel that is assigned to that type of object. The network was then trained using a computer to identify the objects in front of it by learning the pattern of diffracted light each object produced as the light from that object passes through the device. What are its advantages? Scalable: It can easily be scaled up using numerous high-throughput and large-area 3D fabrication methods, such as, soft-lithography, additive manufacturing, and wide-field optical components and detection systems. Easily reconfigurable: D2NN can be easily improved by additional 3D printed layers or replacing some of the existing layers with newly trained ones. Lightening speed: Once the device is trained, it works at the speed of light. Efficient: No energy is consumed to run the device. Cost-effective: The device can be reproduced for less than $50, making it very cost-effective. What are the areas it can be used in? Image analysis Feature detection Object classification Can also enable new microscope or camera designs that can perform unique imaging tasks This new AI device could find applications in the area of medical technologies, data intensive tasks, robotics, security, and or any application where image and video data are essential. Refer to UCLA’s official news article to know more in detail. Also, you can refer to this paper  All-optical machine learning using diffractive deep neural Networks. OpenAI builds reinforcement learning based system giving robots human like dexterity Datasets and deep learning methodologies to extend image-based applications to videos AutoAugment: Google’s research initiative to improve deep learning performance
Read more
  • 0
  • 0
  • 14700
article-image-unity-game-engine-assets-2d-game-development
Amarabha Banerjee
08 Aug 2018
9 min read
Save for later

Implementing Unity game engine and assets for 2D game development [Tutorial]

Amarabha Banerjee
08 Aug 2018
9 min read
The rise of mobile platforms has been in part thanks to its popularity with indie developers, who prefer the short development cycles. The most prevalent medium on mobile is 2D and Unity has a host of features that support 2D game development, including Sprite Editing and Packing, as well as physics specifically designed for 2D games. In this tutorial, we will look at creating Unity game engine and assets for 2D games. This article is an excerpt from the book Unity 2017 Game Development Essentials written by Tommaso Lintrami.  Setting up the scene and preparing game assets Create a new scene from the main menu by navigating to Assets | Create | Scene, and name it ParallaxGame. In this new scene, we will set up, step by step, all the elements for our 2D game prototype. First of all, we will switch the camera setting in the Scene view to 2D by clicking on the button as shown by the red arrow in the following screenshot: As you can see, now the Scene view camera is orthographic. You can't rotate it as you wish, as you can do with the 3D camera. Of course, we will want to change this setting on our Main Camera as well. Also, we want to change the Orthographic size to 4.5 to have the correct view of the scene. Instead, for the Skybox, we will choose a very dark or black color as clear color in the depth setting. This is how the Inspector should look when these settings are done: While the Clipping Planes distances are important for setting the size of the frustum cone of a 3D, for the Perspective camera (inside which everything will be rendered by the engine), we should only set the Orthographic Size to 4.5, to have the correct distance of the 2D camera from the scene. When these settings are done, proceed by importing Chapter2-3-4.unitypackage into the project. You can either double-click on the package file with Unity open, or use the top menu: Assets | Import | Custom Package. If you haven't imported all the materials from the book's code already, be sure to include the Sprites subfolder. After the import, look in the Sprites/Parallax/DarkCave folder in the Project view and you will find some images imported as textures (as per default). The first thing we want to do now is to change the import settings of these images, in the Inspector, from Texture to Sprite (2D and UI). To do so, select all the images in the Project view in the Sprites/Parallax/DarkCave folder, all except the _reference_main_post file. Which is just a picture used as a reference of what the game level should look like: The Import Settings shown in the Inspector after selecting the seven images in the Project view The Max Size setting is hidden (-) because we have a multi-selection of image files. After having made the multiple selections, again, in the Inspector, we will do the following: Set the Texture Type option to Sprites (2D and UI). By default, images are imported as textures; to import them as Sprites, this type must be set. Uncheck the Generate Mip Maps option as we don't need MIP maps for this project as we are not going to look at the Sprites from a distant point of view, for example, games with the zoom-in/zoom-out feature (like the original Grand Theft Auto 2D game) would need this setting checked. Set Max Size to the maximum allowed. To ensure that you import all the images at their maximum resolution, set this to 8192. This is the maximum resolution size for an image on a modern PC, imported as a Sprite or texture. We set it so high because most of the background images we have in the collection are around 6,000 pixels wide. Click on the Apply button to apply these changes to all the images that were selected: The Project view showing the content of the folder after the images have been set to Sprite in the Import Settings Placing the prefabs in the game Unity can place the prefabs in the game in many ways, the usual, visual method is to drag a stored prefab or another kind of file/object directly into the scene. Before dragging in the Sprites we imported, we will create an empty GameObject and rename it ParallaxCave. We will drag the layer images we just imported as Sprites, one by one, from the Project view (pointing at the Assets/Chapters2-3-4/Sprites/Background/DarkCave folder) into the Scene view, or more simply, directly in the Hierarchy view as the children of our ParallaxCave GameObject, resulting in a scene Hierarchy like the one illustrated here: You can't drag all of them instantly because Unity will prompt you to save an animation filename for the selected collection of Sprites; we will see this later for our character and for the collectable graphics. The ParallaxCave GameObject and its children are in blue because this GameObject is stored as a prefab. When the link with the prefab is broken for a modification, the GameObject in the Hierarchy will become black again. When you see a red GameObject in the scene, it means that the prefab file that was linked to that GameObject was deleted. Importing and placing background layers In any game engine, 2D elements, such as Sprites, are rendered following a sort order; this order is also called the z-order because it is a way to express the depth or to cope with the missing z axis in a two-dimensional context. The sort order is assigned an integer number which can be positive or negative; 0 is the middle point of this draw order. Ideally, a sort order of zero expresses the middle ground, where the player will act, or near its layer. Look at this image: All positive numbers will render the Sprite element in front of the other elements with a lower number. The graphic set we are going to use was taken from the Open Game Art website at http://opengameart.org. For simplicity, the provided background image files are named with a number within parentheses, for example, middleground(z1), which means that this image should be rendered with a z sort order of 1. Change the sort order property of the Sprite component on each child object under ParallaxCave according to the value in the parentheses at the end of their filenames. This will rearrange the graphics into the appropriately sorted order. After we place and set the correct layer order for all the images, we should arrange and scale the layers in a proper manner to end as something like the reference image furnished in the Assets/Chapters2-3-4/Sprites/Background/DarkCave/ folder. You can take a look at the final result for this part anytime, by saving the current scene and loading the Chapter3_start.unity scene. On the optimization side, Sprites can be packed together in a single atlas texture with the Sprite Packer into a single image atlas (a single image containing a whole group of Sprites). Implementing parallax scrolling Parallax scrolling is a graphic technique where the background content (that is, an image) is moved at a different speed than the foreground content while scrolling. The technique was derived from the multiplane camera technique used in traditional animation since the 1930s. Parallax scrolling was popular in the 1980s and early 1990s and started to see light with video games such as Moon Patrol and Jungle Hunt, both released in 1982. On such a display system, a game can produce parallax by simply changing each layer's position by a different amount in the same direction. Layers that move more quickly are perceived to be closer to the virtual camera. Layers can be placed in front of the playfield, the layer containing the objects with which the player interacts, for various reasons, such as to provide increased dimension, obscure some of the action of the game, or distract the player. Here follows a short list of the first parallax scrolling games which made the history of video games: Moon Patrol (Atari, 1982) https://youtu.be/HBOKWCpwGfM https://en.wikipedia.org/wiki/Moon_Patrol Shadow of the Beast (Psygnosis, 1989) https://youtu.be/w6Osnolfxqw https://en.wikipedia.org/wiki/Shadow_of_the_Beast Super Mario World (Nintendo, 1990) https://www.youtube.com/watch?v=htFJTiVH5Ao https://en.wikipedia.org/wiki/Super_Mario_World Sonic The Hedgehog (Sega, 1991) https://youtu.be/dws4ij2IFH4 https://en.wikipedia.org/wiki/Sonic_the_Hedgehog_(1991_video_game) Making it last forever There are many roads we could take to make the hero run last forever and to achieve parallax scrolling. You can find a lot of different ready-made solutions in the Asset Store and there are also many General Public License (GPL) open source pieces of code written in C that we could take inspiration from. Using the Asset Store I chose FreeParallax from the Asset Store because it is powerful, free, and a well-written piece of code. Also, the modifications needed to achieve our game prototype on this class are very few. Let's download and import the system from the Asset Store. First, navigate to http://u3d.as/bvv: Click on the Open in Unity button to allow Unity to open this entry in the Asset Store window. You can, alternatively, search for the package directly in Unity  by opening the store from the top menu: Windows | Asset Store (recommended). In the search box type: parallax; also choose FREE ONLY like in this screenshot: You should now find the correct entry, the Free Parallax for Unity(2D) package. You can now download the package and import it into your project straight away. We saw how to create Unity game engine and assets for 2D games. Check out the book Unity 2017 Game Development Essentials to know more ways of creating interactive 2D games. Unite Berlin 2018 Keynote: Unity partners with Google, launches Ml-Agents ToolKit 0.4, Project MARS AI for Unity game developers: How to emulate real-world senses in your NPC agent Working with Unity Variables to script powerful Unity 2017 games
Read more
  • 0
  • 0
  • 20093

article-image-create-machine-learning-pipelines-using-unsupervised-automl
Sunith Shetty
07 Aug 2018
11 min read
Save for later

Create machine learning pipelines using unsupervised AutoML [Tutorial]

Sunith Shetty
07 Aug 2018
11 min read
AutoML uses unsupervised algorithms for performing an automated process of algorithm selection, hyperparameter tuning, iterative modeling, and model assessment.  When your dataset doesn't have a target variable, you can use clustering algorithms to explore it, based on different characteristics. These algorithms group examples together, so that each group will have examples as similar as possible to each other, but dissimilar to examples in other groups. Since you mostly don't have labels when you are performing such analysis, there is a performance metric that you can use to examine the quality of the resulting separation found by the algorithm. It is called the Silhouette Coefficient. The Silhouette Coefficient will help you to understand two things: Cohesion: Similarity within clusters Separation: Dissimilarity among clusters It will give you a value between 1 and -1, with values close to 1 indicating well-formed clusters. Clustering algorithms are used to tackle many different tasks such as finding similar users, songs, or images, detecting key trends and changes in patterns, understanding community structures in social networks. This tutorial deals with using unsupervised machine learning algorithms for creating machine learning pipelines. The code files for this article are available on Github. This article is an excerpt from a book written by Sibanjan Das, Umit Mert Cakmak titled Hands-On Automated Machine Learning.  Commonly used clustering algorithms There are two types of commonly used clustering algorithms: distance-based and probabilistic models. For example, k-means and Density-Based Spatial Clustering of Applications with Noise (DBSCAN) are distance-based algorithms, whereas the Gaussian mixture model is probabilistic. Distance-based algorithms may use a variety of distance measures where Euclidean distance metrics are usually used. Probabilistic algorithms will assume that there is a generative process with a mixture of probability distributions with unknown parameters and the goal is to calculate these parameters from the data. Since there are many clustering algorithms, picking the right one depends on the characteristics of your data. For example, k-means will work with centroids of clusters and this requires clusters in your data to be evenly sized and convexly shaped. This means that k-means will not work well on elongated clusters or irregularly shaped manifolds. When your clusters in your data are not evenly sized or convexly shaped, you many want to use DBSCAN to cluster areas of any shape. Knowing a thing or two about your data will bring you closer to finding the right algorithms, but what if you don't know much about your data? Many times when you are performing exploratory analysis, it might be hard to get your head around what's happening. If you find yourself in this kind of situation, an automated unsupervised ML pipeline can help you to understand the characteristics of your data better. Be careful when you perform this kind of analysis, though; the actions you will take later will be driven by the results you will see and this could quickly send you down the wrong path if you are not cautious. Creating sample datasets with sklearn In sklearn, there are some useful ways to create sample datasets for testing algorithms: # Importing necessary libraries for visualization import matplotlib.pyplot as plt import seaborn as sns # Set context helps you to adjust things like label size, lines and various elements # Try "notebook", "talk" or "paper" instead of "poster" to see how it changes sns.set_context('poster') # set_color_codes will affect how colors such as 'r', 'b', 'g' will be interpreted sns.set_color_codes() # Plot keyword arguments will allow you to set things like size or line width to be used in charts. plot_kwargs = {'s': 10, 'linewidths': 0.1} import numpy as np import pandas as pd # Pprint will better output your variables in console for readability from pprint import pprint # Creating sample dataset using sklearn samples_generator from sklearn.datasets.samples_generator import make_blobs from sklearn.preprocessing import StandardScaler # Make blobs will generate isotropic Gaussian blobs # You can play with arguments like center of blobs, cluster standard deviation centers = [[2, 1], [-1.5, -1], [1, -1], [-2, 2]] cluster_std = [0.1, 0.1, 0.1, 0.1] # Sample data will help you to see your algorithms behavior X, y = make_blobs(n_samples=1000, centers=centers, cluster_std=cluster_std, random_state=53) # Plot generated sample data plt.scatter(X[:, 0], X[:, 1], **plot_kwargs) plt.show() We get the following plot from the preceding code: cluster_std will affect the amount of dispersion. Change it to [0.4, 0.5, 0.6, 0.5] and try again: cluster_std = [0.4, 0.5, 0.6, 0.5] X, y = make_blobs(n_samples=1000, centers=centers, cluster_std=cluster_std, random_state=53) plt.scatter(X[:, 0], X[:, 1], **plot_kwargs) plt.show() We get the following plot from the preceding code: Now it looks more realistic! Let's write a small class with helpful methods to create unsupervised experiments. First, you will use the fit_predict method to apply one or more clustering algorithms on the sample dataset: class Unsupervised_AutoML: def __init__(self, estimators=None, transformers=None): self.estimators = estimators self.transformers = transformers pass Unsupervised_AutoML class will initialize with a set of estimators and transformers. The second class method will be fit_predict: def fit_predict(self, X, y=None): """ fit_predict will train given estimator(s) and predict cluster membership for each sample """ # This dictionary will hold predictions for each estimator predictions = [] performance_metrics = {} for estimator in self.estimators: labels = estimator['estimator'](*estimator['args'], **estimator['kwargs']).fit_predict(X) estimator['estimator'].n_clusters_ = len(np.unique(labels)) metrics = self._get_cluster_metrics(estimator['estimator'].__name__, estimator['estimator'].n_clusters_, X, labels, y) predictions.append({estimator['estimator'].__name__: labels}) performance_metrics[estimator['estimator'].__name__] = metrics self.predictions = predictions self.performance_metrics = performance_metrics return predictions, performance_metrics The fit_predict method uses the _get_cluster_metrics method to get the performance metrics, which is defined in the following code block: # Printing cluster metrics for given arguments def _get_cluster_metrics(self, name, n_clusters_, X, pred_labels, true_labels=None): from sklearn.metrics import homogeneity_score, completeness_score, v_measure_score, adjusted_rand_score, adjusted_mutual_info_score, silhouette_score print("""################## %s metrics #####################""" % name) if len(np.unique(pred_labels)) >= 2: silh_co = silhouette_score(X, pred_labels) if true_labels is not None: h_score = homogeneity_score(true_labels, pred_labels) c_score = completeness_score(true_labels, pred_labels) vm_score = v_measure_score(true_labels, pred_labels) adj_r_score = adjusted_rand_score(true_labels, pred_labels) adj_mut_info_score = adjusted_mutual_info_score(true_labels, pred_labels) metrics = {"Silhouette Coefficient": silh_co, "Estimated number of clusters": n_clusters_, "Homogeneity": h_score, "Completeness": c_score, "V-measure": vm_score, "Adjusted Rand Index": adj_r_score, "Adjusted Mutual Information": adj_mut_info_score} for k, v in metrics.items(): print("t%s: %0.3f" % (k, v)) return metrics metrics = {"Silhouette Coefficient": silh_co, "Estimated number of clusters": n_clusters_} for k, v in metrics.items(): print("t%s: %0.3f" % (k, v)) return metrics else: print("t# of predicted labels is {}, can not produce metrics. n".format(np.unique(pred_labels))) The _get_cluster_metrics method calculates metrics, such as homogeneity_score, completeness_score, v_measure_score, adjusted_rand_score, adjusted_mutual_info_score, and silhouette_score. These metrics will help you to assess how well the clusters are separated and also measure the similarity within and between clusters. K-means algorithm in action You can now apply the KMeans algorithm to see how it works: from sklearn.cluster import KMeans estimators = [{'estimator': KMeans, 'args':(), 'kwargs':{'n_clusters': 4}}] unsupervised_learner = Unsupervised_AutoML(estimators) You can see the estimators: unsupervised_learner.estimators These will output the following: [{'args': (), 'estimator': sklearn.cluster.k_means_.KMeans, 'kwargs': {'n_clusters': 4}}] You can now invoke fit_predict to obtain predictions and performance_metrics: predictions, performance_metrics = unsupervised_learner.fit_predict(X, y) Metrics will be written to the console: ################## KMeans metrics ##################### Silhouette Coefficient: 0.631 Estimated number of clusters: 4.000 Homogeneity: 0.951 Completeness: 0.951 V-measure: 0.951 Adjusted Rand Index: 0.966 Adjusted Mutual Information: 0.950 You can always print metrics later: pprint(performance_metrics) This will output the name of the estimator and its metrics: {'KMeans': {'Silhouette Coefficient': 0.9280431207593165, 'Estimated number of clusters': 4, 'Homogeneity': 1.0, 'Completeness': 1.0, 'V-measure': 1.0, 'Adjusted Rand Index': 1.0, 'Adjusted Mutual Information': 1.0}} Let's add another class method to plot the clusters of the given estimator and predicted labels: # plot_clusters will visualize the clusters given predicted labels def plot_clusters(self, estimator, X, labels, plot_kwargs): palette = sns.color_palette('deep', np.unique(labels).max() + 1) colors = [palette[x] if x >= 0 else (0.0, 0.0, 0.0) for x in labels] plt.scatter(X[:, 0], X[:, 1], c=colors, **plot_kwargs) plt.title('{} Clusters'.format(str(estimator.__name__)), fontsize=14) plt.show() Let's see the usage: plot_kwargs = {'s': 12, 'linewidths': 0.1} unsupervised_learner.plot_clusters(KMeans, X, unsupervised_learner.predictions[0]['KMeans'], plot_kwargs) You get the following plot from the preceding block: In this example, clusters are evenly sized and clearly separate from each other but, when you are doing this kind of exploratory analysis, you should try different hyperparameters and examine the results. You will write a wrapper function later in this article to apply a list of clustering algorithms and their hyperparameters to examine the results. For now, let's see one more example with k-means where it does not work well. When clusters in your dataset have different statistical properties, such as differences in variance, k-means will fail to identify clusters correctly: X, y = make_blobs(n_samples=2000, centers=5, cluster_std=[1.7, 0.6, 0.8, 1.0, 1.2], random_state=220) # Plot sample data plt.scatter(X[:, 0], X[:, 1], **plot_kwargs) plt.show() We get the following plot from the preceding code: Although this sample dataset is generated with five centers, it's not that obvious and there might be four clusters, as well: from sklearn.cluster import KMeans estimators = [{'estimator': KMeans, 'args':(), 'kwargs':{'n_clusters': 4}}] unsupervised_learner = Unsupervised_AutoML(estimators) predictions, performance_metrics = unsupervised_learner.fit_predict(X, y) Metrics in the console are as follows: ################## KMeans metrics ##################### Silhouette Coefficient: 0.549 Estimated number of clusters: 4.000 Homogeneity: 0.729 Completeness: 0.873 V-measure: 0.795 Adjusted Rand Index: 0.702 Adjusted Mutual Information: 0.729 KMeans clusters are plotted as follows: plot_kwargs = {'s': 12, 'linewidths': 0.1} unsupervised_learner.plot_clusters(KMeans, X, unsupervised_learner.predictions[0]['KMeans'], plot_kwargs) We get the following plot from the preceding code: In this example, points between red (dark gray) and bottom-green clusters (light gray) seem to form one big cluster. K-means is calculating the centroid based on the mean value of points surrounding that centroid. Here, you need to have a different approach. The DBSCAN algorithm in action DBSCAN is one of the clustering algorithms that can deal with non-flat geometry and uneven cluster sizes. Let's see what it can do: from sklearn.cluster import DBSCAN estimators = [{'estimator': DBSCAN, 'args':(), 'kwargs':{'eps': 0.5}}] unsupervised_learner = Unsupervised_AutoML(estimators) predictions, performance_metrics = unsupervised_learner.fit_predict(X, y) Metrics in the console are as follows: ################## DBSCAN metrics ##################### Silhouette Coefficient: 0.231 Estimated number of clusters: 12.000 Homogeneity: 0.794 Completeness: 0.800 V-measure: 0.797 Adjusted Rand Index: 0.737 Adjusted Mutual Information: 0.792 DBSCAN clusters are plotted as follows: plot_kwargs = {'s': 12, 'linewidths': 0.1} unsupervised_learner.plot_clusters(DBSCAN, X, unsupervised_learner.predictions[0]['DBSCAN'], plot_kwargs) We get the following plot from the preceding code: Conflict between red (dark gray) and bottom-green (light gray) clusters from the k-means case seems to be gone, but what's interesting here is that some small clusters appeared and some points were not assigned to any cluster based on their distance. DBSCAN has the eps(epsilon) hyperparameter, which is related to proximity for points to be in same neighborhood; you can play with that parameter to see how the algorithm behaves. When you are doing this kind of exploratory analysis where you don't know much about the data, visual clues are always important, because metrics can mislead you since not every clustering algorithm can be assessed using similar metrics. To summarize we learned about many different aspects when it comes to choosing a suitable ML pipeline for a given problem. You gained a better understanding of how unsupervised algorithms may suit your needs for a given problem. To have a clearer understanding of the different aspects of automated Machine Learning, and how to incorporate automation tasks using practical datasets, check out this book Hands-On Automated Machine Learning. Read more Google announces Cloud TPUs on the Cloud Machine Learning Engine (ML Engine) How machine learning as a service is transforming cloud Selecting Statistical-based Features in Machine Learning application
Read more
  • 0
  • 0
  • 24434
Modal Close icon
Modal Close icon