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

7010 Articles
article-image-cloud-computing-trends-in-2019
Guest Contributor
07 Jan 2019
8 min read
Save for later

Cloud computing trends in 2019

Guest Contributor
07 Jan 2019
8 min read
Cloud computing is a rapidly growing technology that many organizations are adopting to enable their digital transformation. As per the latest Gartner report, the cloud tech services market is projected to grow 17.3% ($206 billion) in 2019, up from $175.8 billion in 2018 and by 2022, 90% of organizations will be using cloud services. In today’s world, Cloud technology is a trending buzzword among business environments. It provides exciting new opportunities for businesses to compete on a global scale and is redefining the way we do business. It enables a user to store and share data like applications, files, and more to remote locations. These features have been realized by all business owners, from startup to well-established organizations, and they have already started using cloud computing. How Cloud technology helps businesses Reduced Cost One of the most obvious advantages small businesses can get by shifting to the cloud is saving money. It can provide small business with services at affordable and scalable prices. Virtualization expands the value of physical equipment, which means companies can achieve more with less. Therefore, an organization can see a significant decline in power consumption, rack space, IT requirements, and more. As a result, there is lower maintenance, installation, hardware, support & upgrade costs. For small businesses, particularly, those savings are essential. Enhanced Flexibility Cloud can access data and related files from any location and from any device at any time with an internet connection. As the working process is changing to flexible and remote working, it is essential to provide work-related data access to employees, even when they are not at a workplace. Cloud computing not only helps employees to work outside of the office premises but also allows employers to manage their business as and when required. Also, enhanced flexibility & mobility in cloud technology can lead to additional cost savings. For example, an employer can select to execute BYOD (bring your own device). Therefore, employees can bring and work on their own devices which they are comfortable in.. Secured Data Improved data security is another asset of cloud computing. With traditional data storage systems, the data can be easily stolen or damaged. There can also be more chances for serious cyber attacks like viruses, malware, and hacking. Human errors and power outages can also affect data security. However, if you use cloud computing, you will get the advantages of improved data security. In the cloud, the data is protected in various ways such as anti-virus, encryption methods, and many more. Additionally, to reduce the chance of data loss, the cloud services help you to remain in compliance with HIPAA, PCI, and other regulations. Effective Collaboration Effective collaboration is possible through the cloud which helps small businesses to track and oversee workflow and progress for effective results. There are many cloud collaboration tools available in the market such as Google Drive, Salesforce, Basecamp, Hive, etc. These tools allow users to create, edit, save and share documents for workplace collaboration. A user can also constrain the access of these materials. Greater Integration Cloud-based business solutions can create various simplified integration opportunities with numerous cloud-based providers. They can also get benefits of specialized services that integrate with back-office operations such as HR, accounting, and marketing. This type of integration makes business owners concentrate on the core areas of a business. Scalability One of the great aspects of cloud-based services is their scalability. Currently, a small business may require limited storage, mobility, and more. But in future, needs & requirements will increase significantly in parallel with the growth of the business.  Considering that growth does not always occur linearly, cloud-based solutions can accommodate all sudden and increased requirements of the organization. Cloud-based services have the flexibility to scale up or to scale down. This feature ensures that all your requirements are served according to your budget plans. Cloud Computing Trends in 2019 Hybrid & Multi-Cloud Solutions Hybrid Cloud will become the dominant business model in the future. For organizations, the public cloud cannot be a good fit for all type of solutions and shifting everything to the cloud can be a difficult task as they have certain requirements. The Hybrid Cloud model offers a transition solution that blends the current on-premises infrastructure with open cloud & private cloud services. Thus, organizations will be able to shift to the cloud technology at their own pace while being effective and flexible. Multi-Cloud is the next step in the cloud evolution. It enables users to control and run an application, workload, or data on any cloud (private, public and hybrid) based on their technical requirements. Thus, a company can have multiple public and private clouds or multiple hybrid clouds, all either connected together or not. We can expect multi-cloud strategies to dominate in the coming days. Backup and Disaster Recovery According to Spiceworks report,  15% of the cloud budget is allocated to Backup and Disaster Recovery (DR) solutions, which is the highest budget allocation, followed by email hosting and productivity tools. This huge percentage impacts the shared responsibility model that public cloud providers operate on. Public cloud providers, like as AWS (Amazon Web Services ), Microsoft Azure, Google Cloud are responsible for the availability of Backup and DR solutions and security of the infrastructure, while the users are in charge for their data protection and compliance. Serverless Computing Serverless Computing is gaining more popularity and will continue to do so in 2019. It is a procedure utilized by Cloud users, who request a container PaaS (Platform as a Service), and Cloud supplier charges for the PaaS as required. The customer does not need to buy or rent services before and doesn't need to configure them. The Cloud is responsible for providing the platform, it’s configuration, and a wide range of helpful tools for designing applications, and working with data. Data Containers The process of Data Container usage will become easier in 2019. Containers are more popular for transferring data, they store and organize virtual objects, and resolve the issues of having software run reliably while transferring the data from one system to another. However, there are some confinements. While containers are used to transport, they can only be used with servers having compatible operating system “kernels.” Artificial Intelligence Platforms The utilization of AI to process Big Data is one of the more important upgrades in collecting business intelligence data and giving a superior comprehension of how business functions. AI platform supports a faster, more effective, and more efficient approach to work together with data scientists and other team members. It can help to reduce costs in a variety of ways, such as making simple tasks automated, preventing the duplication of effort, and taking over some expensive labor tasks, such as copying or extraction of data. Edge computing Edge computing is a systematic approach to execute data processing at the edge of the network to streamline cloud computing. It is a result of ever increased use of IoT devices. Edge is essential to run real-time services as it streamlines the flow of traffic from IoT devices and provides real-time data analytics and analysis. Hence, it is also on the rise in 2019. Service mesh Service mesh is a dedicated system layer to enhance service to service communication across microservices applications. It's a new and emerging class of service management for the inter-microservice communication complexity and provides observability and tracing in a seamless way. As containers become more prevalent for cloud-based application development, the requirement for service mesh is increasing significantly. Service meshes can help oversee traffic through service discovery, load balancing, routing, and observability. Service meshes attempt to diminish the complexity of containers and improve network functionality. Cloud Security As we see the rise in technology, security is obviously another serious consideration. With the introduction of the GDPR (General Data Protection Regulation) security concerns have risen much higher and are the essential thing to look after. Many businesses are shifting to cloud computing without any serious consideration of its security compliance protocols. Therefore, GDPR will be an important thing in 2019 and the organization must ensure that their data practices are both safe and compliant. Conclusion As we discussed above, cloud technology is capable of providing better data storage, data security, collaboration, and it also changes the workflow to help small business owners to take better decisions. Finally, cloud connectivity is all about convenience, and streamlining workflow to help any business become more flexible, efficient, productive, and successful. If you want to set your business up for success, this might be the time to transition to cloud-based services. Author Bio Amarendra Babu L loves pursuing excellence through writing and has a passion for technology. He is presently working as a content contributor for Mindmajix.com and Tekslate.com. He is a tech-geek and love to explore new opportunities. His work has been published on various sites related to Big Data, Business Analytics & Intelligence, Blockchain, Cloud Computing, Data Science, AI & ML, Project Management, and more. You can reach him at amarendrabl18@gmail.com. He is also available on Linkedin. 8 programming languages to learn in 2019 18 people in tech every programmer and software engineer need to follow in 2019 We discuss the key trends for web and app developers in 2019 [Podcast]
Read more
  • 0
  • 0
  • 42518

article-image-setting-up-a-raspberry-pi-for-a-robot-headless-by-default-tutorial
Prasad Ramesh
07 Jan 2019
12 min read
Save for later

Setting up a Raspberry Pi for a robot - Headless by Default [Tutorial]

Prasad Ramesh
07 Jan 2019
12 min read
In this tutorial, you will learn why the Raspberry Pi controller on a robot should be wireless, or headless; what headless means; and why it's useful in robotics. You will see how to set up a Raspberry Pi as a headless device from the beginning, and how to connect to this Raspberry Pi once on the network, and then send your first instructions to it. This article is an excerpt from a book written by Danny Staple titled Learn Robotics Programming. In this book, you will learn you'll gain experience of building a next-generation collaboration robot What does headless mean and why? A headless system is a computer designed to be used from another computer via a network, for when keyboard, screen, and mouse access to a device is inconvenient. Headless access is used for server systems and for building robots. Refer to the following diagram: The preceding diagram shows a system with a head where a user can sit in front of the device. You would need to take a screen, keyboard, and mouse with your robot—not very mobile. You may be able to attach/detach them as required, but this is also inconvenient and adds bulk. There are systems designed to dock with Raspberry Pis like this and are portable, but when a robot moves, you'd need to disconnect or move with the robot. I have seen, at some events, a robot with a tiny screen attached and someone using a wireless keyboard and mouse as an option. However, in this article we are going to focus on using a robot as a headless device. Take a look at the following diagram: The Raspberry Pi in the preceding diagram is mounted on a robot as a headless device. This Raspberry Pi is connected to batteries and motors, but not encumbered by a screen and keyboard; those are handled by another computer. The Pi is connected wirelessly to a network, which could be through a laptop. Code, instructions, and information are sent to and from the Raspberry Pi via this wireless network. To interact with it, you use the screen and keyboard on your laptop. However, you would usually expect your robot to function autonomously, so you would only connect to the Pi to modify things or test code. As an alternative to bringing a laptop to control a robot everywhere, it can be more convenient to add a few indicator LEDs so you can start and stop autonomous behaviors, view the robot's status, or just drive it without needing to hook up the laptop at all. This Raspberry Pi is free from the screen and keyboard. Most of the time, a screen and keyboard are not required. However, it is worth having them around for the few cases in which you lose contact with the Raspberry Pi and it refuses to respond via the network. You can then use a screen and keyboard to connect with it and see what is going on. For our headless access to the Raspberry Pi, we will be using the SSH system, a secure shell. SSH gives you a command line to send instructions to the Pi and a file transfer system to put files onto it. As SSH connects over a network, we need to configure our Raspberry Pi to connect to your own wireless network. Making a Pi headless makes it free to roam around. It keeps a robot light by not needing to carry or power a screen and keyboard. Being headless makes a robot smaller since a screen and keyboard are bulkier. It also encourages you, the maker, to think more about autonomous behavior since you can't always type commands to the robot. Setting up wireless on the Raspberry Pi and enabling SSH To make your Raspberry Pi headless, we need to set up Wi-Fi. First, you will need to insert a MicroSD card prepared using Raspbian into your computer. To prepare your MicroSD card (at least 16GB) follow these steps: Go to https://www.raspberrypi.org/software/operating-systems/ and download the ZIP file of Raspbian Lite. Download Etcher and install it. Connect your MicroSD to your computer and select the downloaded Raspbian Lite file. The flash button will be highlighted, press it and the process should be completed in a few minutes. If you are continuing straight here from Etcher, you should remove the card and reinsert it so that the computer can recognize the new state of the drive. You will see the card shows up as two disk drives. One of the drives is called boot; this is the only one that you can read in Windows. Windows will ask if you want to format one of these disks. Click Cancel when Windows asks you. This is because part of the SD card holds a Linux-specific filesystem that is not readable by Windows. In boot, you'll need to create two files: ssh: Create this as an empty file with no extension wpa_supplicant.conf: This file will contain your Wi-Fi network configuration It is important that the SSH file has no extension, so it is not ssh.txt or some other variation. Windows will hide extensions by default so you may need to reveal them. On Windows, in File Explorer, go to the View tab, look for the Show/Hide pane, and then tick File name extensions. In general, when working with code, having the extensions displayed is important so I recommend leaving this option ticked. The wpa_supplicant.conf file The first line you must provide in the wpa_supplicant.conf file is a country code. These are known as iso/iec alpha2 country codes and you should find the appropriate country code for the country you are in, by going to https://datahub.io/core/country-list. This is important, as the Wi-Fi adapter will be disabled by Raspbian if this is not present, to prevent it from operating outside the country's legal standard, and interfering or being interfered with by other equipment. In my case, I am in Great Britain, so my country code is GB. Let's take a look at the code: country=GB Then, add the following lines. update_config means that other tools used later are allowed to update the configuration: update_config=1 ctrl_interface=/var/run/wpa_supplicant Now, you can define the Wi-Fi network your robot and Raspberry Pi will connect to: network={ ssid="<your network ssid>" psk="<your network psk>" } Please be sure to specify your own network details instead of the placeholders here. The pre-shared key (PSK) is also known as the Wi-Fi password. These should be the same details you use to connect your laptop or computer to your Wi-Fi network. The completed wpa_supplicant.conf file should look like this: country=GB update_config=1 ctrl_interface=/var/run/wpa_supplicant network={ ssid="<your network ssid>" psk="<your network psk>" } Ensure you use the menus to eject the MicroSD card so the files are fully written before removing it. Now, with these two files in place, you can use the MicroSD Card to boot the Raspberry Pi. Plug the MicroSD card into the slot on the underside of the Raspberry Pi. The contacts of the MicroSD card should be facing the Raspberry Pi in the slot; it will only fit properly into the slot in the correct orientation. Plug a Micro-USB cable into the side of the Raspberry Pi and connect it to a power supply. As the technical requirements suggested, you should have a power supply able to provide around 2.1 amps. Lights turning on means that it is starting. Finding your Pi on the network Assuming your SSID and PSK are correct, your Raspberry Pi will now have registered on your Wi-Fi network. However, now you need to find it. The Raspberry Pi will use dynamic addresses (DHCP), so every time you connect it to your network, it may get a different address; linking to your router and writing down the IP address can work in the short term, but doing that every time it changes would be quite frustrating. Luckily, the Raspberry Pi uses a technology known as mDNS to tell nearby computers that it is there. mDNS is the Multicast Domain Name System, which just means that the Raspberry Pi sends messages to all nearby computers, if they are listening, to say that its name is raspberrypi.local and giving the address to find it. This is also known as Zeroconf and Bonjour. So, the first thing you'll need to do is ensure your computer is able to receive this. Apple macOS If you are using an Apple Mac computer, it is already running the Bonjour software, which is already mDNS capable. Microsoft Windows On Windows, you will need the Bonjour software. If you have already installed a recent version of Skype or iTunes, you will already have this software. You can use this guide (https://smallbusiness.chron.com/enable-bonjour-65245.html) to check that it is already present and enable it. You can check whether it is already working with the following command in a Command Window: C:\Users\danny>ping raspberrypi.local If you see this, you have Bonjour already: PING raspberrypi.local (192.168.0.53) 56(84) bytes of data. 64 bytes from 192.168.0.53 (192.168.0.53): icmp_seq=1 ttl=64 time=0.113 ms 64 bytes from 192.168.0.53 (192.168.0.53): icmp_seq=2 ttl=64 time=0.079 ms If you see this, you'll need to install it: Ping request could not find host raspberrypi.local. Please check the name and try again. To do so, browse to the Apple Bonjour For Windows site at https://support.apple.com/downloads/bonjour_for_windows and download it, then install Download Bonjour Print Services for Windows. Once this has run, Windows will now be able to ask for mDNS devices by name. Linux Ubuntu and Fedora desktop versions have had mDNS compatibility for a long time. On other Linux desktops, you will need to find their instructions for Zeroconf or Avahi. Many recent ones have this enabled by default. Testing the setup The Raspberry Pi's green light should have stopped blinking and only a red power light should be visible. In Windows, summon a command line by pressing the Windows key and then CMD. In Linux or macOS, summon a Terminal. From this Terminal, we will try to ping the Raspberry Pi, that is, find the Pi on the network and send a small message to elicit a response: ping raspberrypi.local If everything has gone right, the computer will show that it has connected to the Pi: $ ping raspberrypi.local PING raspberrypi.local (192.168.0.53) 56(84) bytes of data. 64 bytes from 192.168.0.53 (192.168.0.53): icmp_seq=1 ttl=64 time=0.113 ms 64 bytes from 192.168.0.53 (192.168.0.53): icmp_seq=2 ttl=64 time=0.079 ms 64 bytes from 192.168.0.53 (192.168.0.53): icmp_seq=3 ttl=64 time=0.060 ms 64 bytes from 192.168.0.53 (192.168.0.53): icmp_seq=4 ttl=64 time=0.047 ms What if you cannot reach the Raspberry Pi? If the Raspberry Pi does not appear to be responding to the ping operation, these are some initial steps you can take to try to diagnose and remedy the situation. If it works already, skip to the next heading. Refer to the following steps: First, double-check your connections. You should have seen a few blinks of green light and a persistent red light. If not, ensure that the SD card is seated firmly and that the power supply can give 2.1 amps. Use your Wi-Fi access point settings with the Pi booted and see if it has taken an IP address there. This may mean that Zeroconf/Bonjour is not running on your computer correctly. If you have not installed it, please go back and do so. If you have and you are on Windows, the different versions of Bonjour print services, Bonjour from Skype, and Bonjour from iTunes can conflict if installed together. Use the Windows add/remove functions to see if there is more than one and remove all Bonjour instances, then install the official one again. Next, turn the power off, take out the SD card, place this back into your computer, and double check that the wpa_supplicant.conf file is present and has the right Wi-Fi details and country code. The most common errors in this file are the following: Incorrect Wi-Fi details Missing quotes or missing or incorrect punctuation Incorrect or missing country code Parts being in the wrong case The SSH file is removed when the Pi boots, so if you are certain it was there and has been removed, this a good sign that the Pi actually booted. Finally, this is where you may need to boot the Pi with a screen and keyboard connected, and attempt to diagnose the issue. The screen will tell you whether there are other issues with wpa_supplicant.conf or other problems. With these problems, it is important to look at the screen text and use this to search the web for answers. I cannot reproduce all those here, as there are many kinds of problems that could occur here. If you cannot find this, I recommend asking on Twitter using the tag #raspberrypi, on Stack Overflow, or in the Raspberry Pi Forums at https://www.raspberrypi.org/forums/. In this article, we explored what headless or wireless means for robots and set up the 'headless' in Raspberry Pi. To learn more about robotics and connecting, configuring the robot check out the book, Learn Robotics Programming. Introducing Strato Pi: An industrial Raspberry Pi Raspberry Pi launches it last board for the foreseeable future: the Raspberry Pi 3 Model A+ available now at $25 Introducing Raspberry Pi TV HAT, a new addon that lets you stream live TV
Read more
  • 0
  • 0
  • 35979

article-image-generating-automated-image-captions-using-nlp-and-computer-vision-tutorial
Melisha Dsouza
06 Jan 2019
18 min read
Save for later

Generating automated image captions using NLP and computer vision [Tutorial]

Melisha Dsouza
06 Jan 2019
18 min read
In this tutorial, we will combine techniques in both computer vision and natural language processing to form a complete image description approach. This will be responsible for constructing computer-generated natural descriptions of any provided images.  The idea is to replace the encoder (RNN layer) in an encoder-decoder architecture with a deep convolutional neural network (CNN) trained to classify objects in images. Normally, the CNN's last layer is the softmax layer, which assigns the probability that each object might be in the image. But if we remove that softmax layer from CNN, we can feed the CNN's rich encoding of the image into the decoder (language generation RNN) designed to produce phrases. We can then train the whole system directly on images and their captions, so it maximizes the likelihood that the descriptions it produces best match the training descriptions for each image. This tutorial is an excerpt from a book written by  Matthew Lamons, Rahul Kumar, Abhishek Nagaraja titled Python Deep Learning Projects. This book will simplify and ease how deep learning works, demonstrating how neural networks play a vital role in exploring predictive analytics across different domains. Users will explore projects in the field of computational linguistics, computer vision, machine translation, pattern recognition and many more! All of the Python files and Jupyter Notebook files for this tutorial can be found at GitHub. In this implementation, we will be using a pretrained Inception-v3 model as a feature extractor in an encoder trained on the ImageNet dataset. Let's import all of the dependencies that we will need to build an auto-captioning model. All of the Python files and the Jupyter Notebooks for this article can be found on GitHub. Initialization For this implementation, we need a TensorFlow version greater than or equal to 1.9 and we will also enable the eager execution mode, which will help us use the debug the code more effectively. Here is the code for this: # Import TensorFlow and enable eager execution import tensorflow as tf tf.enable_eager_execution() import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from sklearn.utils import shuffle import re import numpy as np import os import time import json from glob import glob from PIL import Image import pickle Download and prepare the MS-COCO dataset We are going to use the MS-COCO dataset to train our model. This dataset contains more than 82,000 images, each of which has been annotated with at least five different captions. The following code will download and extract the dataset automatically: annotation_zip = tf.keras.utils.get_file('captions.zip', cache_subdir=os.path.abspath('.'), origin = 'http://images.cocodataset.org/annotations/annotations_trainval2014.zip', extract = True) annotation_file = os.path.dirname(annotation_zip)+'/annotations/captions_train2014.json' name_of_zip = 'train2014.zip' if not os.path.exists(os.path.abspath('.') + '/' + name_of_zip): image_zip = tf.keras.utils.get_file(name_of_zip, cache_subdir=os.path.abspath('.'), origin = 'http://images.cocodataset.org/zips/train2014.zip', extract = True) PATH = os.path.dirname(image_zip)+'/train2014/' else: PATH = os.path.abspath('.')+'/train2014/' The following will be the output: Downloading data from http://images.cocodataset.org/annotations/annotations_trainval2014.zip 252878848/252872794 [==============================] - 6s 0us/step Downloading data from http://images.cocodataset.org/zips/train2014.zip 13510574080/13510573713 [==============================] - 322s 0us/step For this example, we'll select a subset of 40,000 captions and use these and the corresponding images to train our model. As always, captioning quality will improve if you choose to use more data: # read the json annotation file with open(annotation_file, 'r') as f: annotations = json.load(f) # storing the captions and the image name in vectors all_captions = [] all_img_name_vector = [] for annot in annotations['annotations']: caption = '<start> ' + annot['caption'] + ' <end>' image_id = annot['image_id'] full_coco_image_path = PATH + 'COCO_train2014_' + '%012d.jpg' % (image_id) all_img_name_vector.append(full_coco_image_path) all_captions.append(caption) # shuffling the captions and image_names together # setting a random state train_captions, img_name_vector = shuffle(all_captions, all_img_name_vector, random_state=1) # selecting the first 40000 captions from the shuffled set num_examples = 40000 train_captions = train_captions[:num_examples] img_name_vector = img_name_vector[:num_examples] Once the data preparation is completed, we will have all of the image path stored in the img_name_vector list variable, and the associated captions are stored in train_caption, as shown in the following screenshot: Data preparation for a deep CNN encoder Next, we will use Inception-v3 (pretrained on ImageNet) to classify each image. We will extract features from the last convolutional layer. We will create a helper function that will transform the input image to the format that is expected by Inception-v3: #Resizing the image to (299, 299) #Using the preprocess_input method to place the pixels in the range of -1 to 1. def load_image(image_path): img = tf.read_file(image_path) img = tf.image.decode_jpeg(img, channels=3) img = tf.image.resize_images(img, (299, 299)) img = tf.keras.applications.inception_v3.preprocess_input(img) return img, image_path Now let's initialize the Inception-v3 model and load the pretrained ImageNet weights. To do so, we'll create a tf.keras model where the output layer is the last convolutional layer in the Inception-v3 architecture. image_model = tf.keras.applications.InceptionV3(include_top=False, weights='imagenet') new_input = image_model.input hidden_layer = image_model.layers[-1].output image_features_extract_model = tf.keras.Model(new_input, hidden_layer) The output is as follows: Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.5/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5 87916544/87910968 [==============================] - 40s 0us/step So, the image_features_extract_model is our deep CNN encoder, which is responsible for learning the features from the given image. Performing feature extraction Now we will pre-process each image with the deep CNN encoder and dump the output to the disk: We will load the images in batches using the load_image() helper function that we created before We will feed the images into the encoder to extract the features Dump the features as a numpy array: encode_train = sorted(set(img_name_vector)) #Load images image_dataset = tf.data.Dataset.from_tensor_slices( encode_train).map(load_image).batch(16) # Extract features for img, path in image_dataset: batch_features = image_features_extract_model(img) batch_features = tf.reshape(batch_features, (batch_features.shape[0], -1, batch_features.shape[3])) #Dump into disk for bf, p in zip(batch_features, path): path_of_feature = p.numpy().decode("utf-8") np.save(path_of_feature, bf.numpy()) Data prep for a language generation (RNN) decoder The first step is to pre-process the captions. We will perform a few basic pre-processing steps on the captions, such as the following: We'll tokenize the captions (for example, by splitting on spaces). This will help us to build a vocabulary of all the unique words in the data (for example, "playing", "football", and so on). We'll limit the vocabulary size to the top 5,000 words to save memory. We'll replace all other words with the token unk (for unknown). You can obviously optimize that according to the use case. We will then create a word --> index mapping and vice versa. We will finally pad all sequences to be the same length as the longest one. Here is the code for that: # Helper func to find the maximum length of any caption in our dataset def calc_max_length(tensor): return max(len(t) for t in tensor) # Performing tokenization on the top 5000 words from the vocabulary top_k = 5000 tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=top_k, oov_token="<unk>", filters='!"#$%&()*+.,-/:;=?@[\]^_`{|}~ ') # Converting text into sequence of numbers tokenizer.fit_on_texts(train_captions) train_seqs = tokenizer.texts_to_sequences(train_captions) tokenizer.word_index = {key:value for key, value in tokenizer.word_index.items() if value <= top_k} # putting <unk> token in the word2idx dictionary tokenizer.word_index[tokenizer.oov_token] = top_k + 1 tokenizer.word_index['<pad>'] = 0 # creating the tokenized vectors train_seqs = tokenizer.texts_to_sequences(train_captions) # creating a reverse mapping (index -> word) index_word = {value:key for key, value in tokenizer.word_index.items()} # padding each vector to the max_length of the captions cap_vector = tf.keras.preprocessing.sequence.pad_sequences(train_seqs, padding='post') # calculating the max_length # used to store the attention weights max_length = calc_max_length(train_seqs) The end result will be an array of a sequence of integers: We will split the data into training and validation samples using an 80:20 split ratio: img_name_train, img_name_val, cap_train, cap_val = train_test_split(img_name_vector,cap_vector,test_size=0.2,random_state=0) # Checking the sample counts print ("No of Training Images:",len(img_name_train)) print ("No of Training Caption: ",len(cap_train) ) print ("No of Training Images",len(img_name_val)) print ("No of Training Caption:",len(cap_val) ) No of Training Images: 24000 No of Training Caption: 24000 No of Training Images 6000 No of Training Caption: 6000 Setting up the data pipeline Our images and captions are ready! Next, let's create a tf.data dataset to use for training our model. Now we will prepare the pipeline for an image and the text model by performing transformations and batching on them: # Defining parameters BATCH_SIZE = 64 BUFFER_SIZE = 1000 embedding_dim = 256 units = 512 vocab_size = len(tokenizer.word_index) # shape of the vector extracted from Inception-V3 is (64, 2048) # these two variables represent that features_shape = 2048 attention_features_shape = 64 # loading the numpy files def map_func(img_name, cap): img_tensor = np.load(img_name.decode('utf-8')+'.npy') return img_tensor, cap #We use the from_tensor_slices to load the raw data and transform them into the tensors dataset = tf.data.Dataset.from_tensor_slices((img_name_train, cap_train)) # Using the map() to load the numpy files in parallel # NOTE: Make sure to set num_parallel_calls to the number of CPU cores you have # https://www.tensorflow.org/api_docs/python/tf/py_func dataset = dataset.map(lambda item1, item2: tf.py_func( map_func, [item1, item2], [tf.float32, tf.int32]), num_parallel_calls=8) # shuffling and batching dataset = dataset.shuffle(BUFFER_SIZE) dataset = dataset.batch(BATCH_SIZE) dataset = dataset.prefetch(1) Defining the captioning model The model architecture we are using to build the auto captioning is inspired by the Show, Attend and Tell paper. The features that we extracted from the lower convolutional layer of Inception-v3 gave us a vector of a shape of (8, 8, 2048). Then, we squash that to a shape of (64, 2048). This vector is then passed through the CNN encoder, which consists of a single fully connected layer. The RNN (GRU in our case) attends over the image to predict the next word: def gru(units): if tf.test.is_gpu_available(): return tf.keras.layers.CuDNNGRU(units, return_sequences=True, return_state=True, recurrent_initializer='glorot_uniform') else: return tf.keras.layers.GRU(units, return_sequences=True, return_state=True, recurrent_activation='sigmoid', recurrent_initializer='glorot_uniform') Attention Now we will define the attention mechanism popularly known as Bahdanau attention. We will need the features from the CNN encoder of a shape of (batch_size, 64, embedding_dim). This attention mechanism will return the context vector and the attention weights over the time axis: class BahdanauAttention(tf.keras.Model): def __init__(self, units): super(BahdanauAttention, self).__init__() self.W1 = tf.keras.layers.Dense(units) self.W2 = tf.keras.layers.Dense(units) self.V = tf.keras.layers.Dense(1) def call(self, features, hidden): # hidden_with_time_axis shape == (batch_size, 1, hidden_size) hidden_with_time_axis = tf.expand_dims(hidden, 1) # score shape == (batch_size, 64, hidden_size) score = tf.nn.tanh(self.W1(features) + self.W2(hidden_with_time_axis)) # attention_weights shape == (batch_size, 64, 1) # we get 1 at the last axis because we are applying score to self.V attention_weights = tf.nn.softmax(self.V(score), axis=1) # context_vector shape after sum == (batch_size, hidden_size) context_vector = attention_weights * features context_vector = tf.reduce_sum(context_vector, axis=1) return context_vector, attention_weights You can refer to the book to understand the CNN encoder, RNN decoder and Loss function used. Training the captioning model Let's the model. The first thing we need to do is to extract the features stored in the respective .npy files and then pass those features through the CNN encoder. The encoder output, hidden state (initialized to 0) and the decoder input (which is the start token) are passed to the decoder. The decoder returns the predictions and the decoder hidden state. The decoder hidden state is then passed back into the model and the predictions are used to calculate the loss. While training, we use the teacher forcing technique to decide the next input to the decoder. The final step is to calculate the gradient and apply it to the optimizer and backpropagate: EPOCHS = 20 loss_plot = [] for epoch in range(EPOCHS): start = time.time() total_loss = 0 for (batch, (img_tensor, target)) in enumerate(dataset): loss = 0 # initializing the hidden state for each batch # because the captions are not related from image to image hidden = decoder.reset_state(batch_size=target.shape[0]) dec_input = tf.expand_dims([tokenizer.word_index['<start>']] * BATCH_SIZE, 1) with tf.GradientTape() as tape: features = encoder(img_tensor) for i in range(1, target.shape[1]): # passing the features through the decoder predictions, hidden, _ = decoder(dec_input, features, hidden) loss += loss_function(target[:, i], predictions) # using teacher forcing dec_input = tf.expand_dims(target[:, i], 1) total_loss += (loss / int(target.shape[1])) variables = encoder.variables + decoder.variables gradients = tape.gradient(loss, variables) optimizer.apply_gradients(zip(gradients, variables), tf.train.get_or_create_global_step()) if batch % 100 == 0: print ('Epoch {} Batch {} Loss {:.4f}'.format(epoch + 1, batch, loss.numpy() / int(target.shape[1]))) # storing the epoch end loss value to plot later loss_plot.append(total_loss / len(cap_vector)) print ('Epoch {} Loss {:.6f}'.format(epoch + 1, total_loss/len(cap_vector))) print ('Time taken for 1 epoch {} sec\n'.format(time.time() - start)) The following is the output: After performing the training process over few epochs lets plot the Epoch vs Loss graph: plt.plot(loss_plot) plt.xlabel('Epochs') plt.ylabel('Loss') plt.title('Loss Plot') plt.show() The output is as follows: The loss vs Epoch plot during training process Evaluating the captioning model The evaluation function is similar to the training loop, except we don't use teacher forcing here. The input to the decoder at each time step is its previous predictions, along with the hidden state and the encoder output. A few key points to remember while making predictions: Stop predicting when the model predicts the end token Store the attention weights for every time step Let’s define the evaluate() function: def evaluate(image): attention_plot = np.zeros((max_length, attention_features_shape)) hidden = decoder.reset_state(batch_size=1) temp_input = tf.expand_dims(load_image(image)[0], 0) img_tensor_val = image_features_extract_model(temp_input) img_tensor_val = tf.reshape(img_tensor_val, (img_tensor_val.shape[0], -1, img_tensor_val.shape[3])) features = encoder(img_tensor_val) dec_input = tf.expand_dims([tokenizer.word_index['<start>']], 0) result = [] for i in range(max_length): predictions, hidden, attention_weights = decoder(dec_input, features, hidden) attention_plot[i] = tf.reshape(attention_weights, (-1, )).numpy() predicted_id = tf.argmax(predictions[0]).numpy() result.append(index_word[predicted_id]) if index_word[predicted_id] == '<end>': return result, attention_plot dec_input = tf.expand_dims([predicted_id], 0) attention_plot = attention_plot[:len(result), :] return result, attention_plot Also, let's create a helper function to visualize the attention points that predict the words: def plot_attention(image, result, attention_plot): temp_image = np.array(Image.open(image)) fig = plt.figure(figsize=(10, 10)) len_result = len(result) for l in range(len_result): temp_att = np.resize(attention_plot[l], (8, 8)) ax = fig.add_subplot(len_result//2, len_result//2, l+1) ax.set_title(result[l]) img = ax.imshow(temp_image) ax.imshow(temp_att, cmap='gray', alpha=0.6, extent=img.get_extent()) plt.tight_layout() plt.show() # captions on the validation set rid = np.random.randint(0, len(img_name_val)) image = img_name_val[rid] real_caption = ' '.join([index_word[i] for i in cap_val[rid] if i not in [0]]) result, attention_plot = evaluate(image) print ('Real Caption:', real_caption) print ('Prediction Caption:', ' '.join(result)) plot_attention(image, result, attention_plot) # opening the image Image.open(img_name_val[rid]) The output is as follows: Deploying the captioning model We will deploy the complete module as a RESTful service. To do so, we will write an inference code that loads the latest checkpoint and makes the prediction on the given image. Look into the inference.py file in the repository. All the code is similar to the training loop except we don't use teacher forcing here. The input to the decoder at each time step is its previous predictions, along with the hidden state and the encoder output. One important part is to load the model in memory for which we are using the tf.train.Checkpoint() method, which loads all of the learned weights for optimizer, encoder, decoder into the memory. Here is the code for that: checkpoint_dir = './my_model' checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt") checkpoint = tf.train.Checkpoint( optimizer=optimizer, encoder=encoder, decoder=decoder, ) checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir)) So, we will create an evaluate() function, which defines the prediction loop. To make sure that the prediction ends after certain words, we will stop predicting when the model predicts the end token, <end>: def evaluate(image): attention_plot = np.zeros((max_length, attention_features_shape)) hidden = decoder.reset_state(batch_size=1) temp_input = tf.expand_dims(load_image(image)[0], 0) # Extract features from the test image img_tensor_val = image_features_extract_model(temp_input) img_tensor_val = tf.reshape(img_tensor_val, (img_tensor_val.shape[0], -1, img_tensor_val.shape[3])) # Feature is fed into the encoder features = encoder(img_tensor_val) dec_input = tf.expand_dims([tokenizer.word_index['<start>']], 0) result = [] # Prediction loop for i in range(max_length): predictions, hidden, attention_weights = decoder(dec_input, features, hidden) attention_plot[i] = tf.reshape(attention_weights, (-1, )).numpy() predicted_id = tf.argmax(predictions[0]).numpy() result.append(index_word[predicted_id]) # Hard stop when end token is predicted if index_word[predicted_id] == '<end>': return result, attention_plot dec_input = tf.expand_dims([predicted_id], 0) attention_plot = attention_plot[:len(result), :] return result, attention_plot Now let's use this evaluate() function in our web application code: #!/usr/bin/env python2 # -*- coding: utf-8 -*- """ @author: rahulkumar """ from flask import Flask , request, jsonify import time from inference import evaluate import tensorflow as tf app = Flask(__name__) @app.route("/wowme") def AutoImageCaption(): image_url=request.args.get('image') print('image_url') image_extension = image_url[-4:] image_path = tf.keras.utils.get_file(str(int(time.time()))+image_extension, origin=image_url) result, attention_plot = evaluate(image_path) data = {'Prediction Caption:': ' '.join(result)} return jsonify(data) if __name__ == "__main__": app.run(host = '0.0.0.0',port=8081) Execute the following command in the Terminal to run the web app: python caption_deploy_api.py You should get the following output: * Running on http://0.0.0.0:8081/ (Press CTRL+C to quit) Now we request the API, as follows: curl 0.0.0.0:8081/wowme?image=https://www.beautifulpeopleibiza.com/images/BPI/img_bpi_destacada.jpg We should get our caption predicted, as shown in the following screenshot: Make sure to train the model on the large image to get better predictions. Summary In this implementation, we used a pre trained Inception-v3 model as a feature extractor in an encoder trained on the ImageNet dataset as part of a deep learning solution. This solution combines techniques in both computer vision and natural language processing, to form a complete image description approach, able to construct computer-generated natural descriptions of any provided images. We've broken the barrier between images and language with this trained model and we've provided a technology that could be used as part of an application, helping the visually impaired enjoy the benefits of the megatrend of photo sharing! To understand insightful projects to master deep learning and neural network architectures using Python and Keras, check out our book  Python Deep Learning Projects. Getting started with Web Scraping using Python [Tutorial] Google researchers introduce JAX: A TensorFlow-like framework for generating high-performance code from Python and NumPy machine learning programs Google releases Magenta studio beta, an open source python machine learning library for music artists
Read more
  • 0
  • 0
  • 34073

article-image-how-to-build-a-neural-network-to-fill-the-missing-part-of-a-handwritten-digit-using-gans-tutorial
Melisha Dsouza
05 Jan 2019
18 min read
Save for later

How to build a neural network to fill the missing part of a handwritten digit using GANs [Tutorial]

Melisha Dsouza
05 Jan 2019
18 min read
GANs are neural networks used in unsupervised learning that generate synthetic data given certain input data. GAN's have two components: a generator and a discriminator. A generator generates new instances of an object and the discriminator determines whether the new instance belongs to the actual dataset. A generative learn how the data is generated i.e. the structure of the data, in order to categorize it. This allows the system to generate samples with similar statistical properties. Discriminative models will learn the relation between the data and the label associated with the data. The discriminative model will categorize the input data without knowing how the data is generated. GAN exploits the concept behind both the models to get a better network architecture. This tutorial on GAN's will help you build a neural network that fills in the missing part of a handwritten digit. This tutorial will cover how to build an MNIST digit classifier and simulate a dataset of handwritten digits with sections of the handwritten numbers missing. Next, users will learn using the MNIST classifier to predict on noised/masked MNIST digits dataset (simulated dataset) and implement GAN to generate back the missing regions of the digit. This tutorial will also cover using the MNIST classifier to predict on the generated digits from GAN and finally compare performance between masked data and generated data. This tutorial is an excerpt from a book written by  Matthew Lamons, Rahul Kumar, Abhishek Nagaraja titled Python Deep Learning Projects. This book will help users develop their own deep learning systems in a straightforward way and in an efficient way. The book has projects developed using complex deep learning projects in the field of computational linguistics and computer vision to help users master the subject. All of the Python files and Jupyter Notebook files for this tutorial can be found at GitHub. In this tutorial, we will be using the Keras deep learning library. Importing all of the dependencies We will be using numpy, matplotlib, keras, tensorflow, and the tqdm package in this exercise. Here, TensorFlow is used as the backend for Keras. You can install these packages with pip. For the MNIST data, we will be using the dataset available in the keras module with a simple import: import numpy as np import random import matplotlib.pyplot as plt %matplotlib inline from tqdm import tqdm from keras.layers import Input, Conv2D from keras.layers import AveragePooling2D, BatchNormalization from keras.layers import UpSampling2D, Flatten, Activation from keras.models import Model, Sequential from keras.layers.core import Dense, Dropout from keras.layers.advanced_activations import LeakyReLU from keras.optimizers import Adam from keras import backend as k from keras.datasets import mnist It is important that you set seed for reproducibility: # set seed for reproducibility seed_val = 9000 np.random.seed(seed_val) random.seed(seed_val) Exploring the data We will load the MNIST data into our session from the keras module with mnist.load_data(). After doing so, we will print the shape and the size of the dataset, as well as the number of classes and unique labels in the dataset: (X_train, y_train), (X_test, y_test) = mnist.load_data() print('Size of the training_set: ', X_train.shape) print('Size of the test_set: ', X_test.shape) print('Shape of each image: ', X_train[0].shape) print('Total number of classes: ', len(np.unique(y_train))) print('Unique class labels: ', np.unique(y_train)) We have a dataset with 10 different classes and 60,000 images, with each image having a shape of 28*28 and each class having 6,000 images. Let's plot and see what the handwritten images look like: # Plot of 9 random images for i in range(0, 9): plt.subplot(331+i) # plot of 3 rows and 3 columns plt.axis('off') # turn off axis plt.imshow(X_train[i], cmap='gray') # gray scale The output is as follows: Let's plot a handwritten digit from each class: # plotting image from each class fig=plt.figure(figsize=(8, 4)) columns = 5 rows = 2 for i in range(0, rows*columns): fig.add_subplot(rows, columns, i+1) plt.title(str(i)) # label plt.axis('off') # turn off axis plt.imshow(X_train[np.where(y_train==i)][0], cmap='gray') # gray scale plt.show() The output is as follows: Look at the maximum and the minimum pixel value in the dataset: print('Maximum pixel value in the training_set: ', np.max(X_train)) print('Minimum pixel value in the training_set: ', np.min(X_train)) The output is as follows: Preparing the data Type conversion, centering, scaling, and reshaping are some of the pre-processing we will implement in this tutorial. Type conversion, centering and scaling Set the type to np.float32. For centering, we subtract the dataset by 127.5. The values in the dataset will now range between -127.5 to 127.5. For scaling, we divide the centered dataset by half of the maximum pixel value in the dataset, that is, 255/2. This will result in a dataset with values ranging between -1 and 1: # Converting integer values to float types X_train = X_train.astype(np.float32) X_test = X_test.astype(np.float32) # Scaling and centering X_train = (X_train - 127.5) / 127.5 X_test = (X_test - 127.5)/ 127.5 print('Maximum pixel value in the training_set after Centering and Scaling: ', np.max(X_train)) print('Minimum pixel value in the training_set after Centering and Scaling: ', np.min(X_train)) Let's define a function to rescale the pixel values of the scaled image to range between 0 and 255: # Rescale the pixel values (0 and 255) def upscale(image): return (image*127.5 + 127.5).astype(np.uint8) # Lets see if this works z = upscale(X_train[0]) print('Maximum pixel value after upscaling scaled image: ',np.max(z)) print('Maximum pixel value after upscaling scaled image: ',np.min(z)) A plot of 9 centered and scaled images after upscaling: for i in range(0, 9): plt.subplot(331+i) # plot of 3 rows and 3 columns plt.axis('off') # turn off axis plt.imshow(upscale(X_train[i]), cmap='gray') # gray scale The output is as follows: Masking/inserting noise For the needs of this project, we need to simulate a dataset of incomplete digits. So, let's write a function to mask small regions in the original image to form the noised dataset. The idea is to mask an 8*8 region of the image with the top-left corner of the mask falling between the 9th and 13th pixel (between index 8 and 12) along both the x and y axis of the image. This is to make sure that we are always masking around the center part of the image: def noising(image): array = np.array(image) i = random.choice(range(8,12)) # x coordinate for the top left corner of the mask j = random.choice(range(8,12)) # y coordinate for the top left corner of the mask array[i:i+8, j:j+8]=-1.0 # setting the pixels in the masked region to -1 return array noised_train_data = np.array([*map(noising, X_train)]) noised_test_data = np.array([*map(noising, X_test)]) print('Noised train data Shape/Dimension : ', noised_train_data.shape) print('Noised test data Shape/Dimension : ', noised_train_data.shape) A plot of 9 scaled noised images after upscaling: # Plot of 9 scaled noised images after upscaling for i in range(0, 9): plt.subplot(331+i) # plot of 3 rows and 3 columns plt.axis('off') # turn off axis plt.imshow(upscale(noised_train_data[i]), cmap='gray') # gray scale The output is as follows: Reshaping Reshape the original dataset and the noised dataset to a shape of 60000*28*28*1. This is important since the 2D convolutions expect to receive images of a shape of 28*28*1: # Reshaping the training data X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2], 1) print('Size/Shape of the original training set: ', X_train.shape) # Reshaping the noised training data noised_train_data = noised_train_data.reshape(noised_train_data.shape[0], noised_train_data.shape[1], noised_train_data.shape[2], 1) print('Size/Shape of the noised training set: ', noised_train_data.shape) # Reshaping the testing data X_test = X_test.reshape(X_test.shape[0], X_test.shape[1], X_test.shape[2], 1) print('Size/Shape of the original test set: ', X_test.shape) # Reshaping the noised testing data noised_test_data = noised_test_data.reshape(noised_test_data.shape[0], noised_test_data.shape[1], noised_test_data.shape[2], 1) print('Size/Shape of the noised test set: ', noised_test_data.shape) MNIST classifier To start off with modeling, let's build a simple convolutional neural network (CNN) digit classifier. The first layer is a convolution layer that has 32 filters of a shape of 3*3, with relu activation and Dropout as the regularizer. The second layer is a convolution layer that has 64 filters of a shape of 3*3, with relu activation and Dropout as the regularizer. The third layer is a convolution layer that has 128 filters of a shape of 3*3, with relu activation and Dropout as the regularizer, which is finally flattened. The fourth layer is a Dense layer of 1024 neurons with relu activation. The final layer is a Dense layer with 10 neurons corresponding to the 10 classes in the MNIST dataset, and the activation used here is softmax, batch_size is set to 128, the optimizer used is adam, and validation_split is set to 0.2. This means that 20% of the training set will be used as the validation set: # input image shape input_shape = (28,28,1) def train_mnist(input_shape, X_train, y_train): model = Sequential() model.add(Conv2D(32, (3, 3), strides=2, padding='same', input_shape=input_shape)) model.add(Activation('relu')) model.add(Dropout(0.2)) model.add(Conv2D(64, (3, 3), strides=2, padding='same')) model.add(Activation('relu')) model.add(Dropout(0.2)) model.add(Conv2D(128, (3, 3), padding='same')) model.add(Activation('relu')) model.add(Dropout(0.2)) model.add(Flatten()) model.add(Dense(1024, activation = 'relu')) model.add(Dense(10, activation='softmax')) model.compile(loss = 'sparse_categorical_crossentropy', optimizer = 'adam', metrics = ['accuracy']) model.fit(X_train, y_train, batch_size = 128, epochs = 3, validation_split=0.2, verbose = 1 ) return model mnist_model = train_mnist(input_shape, X_train, y_train) The output is as follows: Use the built CNN digit classifier on the masked images to get a measure of its performance on digits that are missing small sections: # prediction on the masked images pred_labels = mnist_model.predict_classes(noised_test_data) print('The model model accuracy on the masked images is:',np.mean(pred_labels==y_test)*100) On the masked images, the CNN digit classifier is 74.9% accurate. It might be slightly different when you run it, but it will still be very close. Defining hyperparameters for GAN The following are some of the hyperparameters defined that we will be using throughout the code and are totally configurable: # Smoothing value smooth_real = 0.9 # Number of epochs epochs = 5 # Batchsize batch_size = 128 # Optimizer for the generator optimizer_g = Adam(lr=0.0002, beta_1=0.5) # Optimizer for the discriminator optimizer_d = Adam(lr=0.0004, beta_1=0.5) # Shape of the input image input_shape = (28,28,1) Building the GAN model components With the idea that the final GAN model will be able to fill in the part of the image that is missing (masked), let's define the generator. You can understand how to define the generator, discriminator, and DCGAN by referring to our book. Training GAN We've built the components of the GAN.  Let's train the model in the next steps! Plotting the training – part 1 During each epoch, the following function plots 9 generated images. For comparison, it will also plot the corresponding 9 original target images and 9 noised input images. We need to use the upscale function we've defined when plotting to make sure the images are scaled to range between 0 and 255, so that you do not encounter issues when plotting: def generated_images_plot(original, noised_data, generator): print('NOISED') for i in range(9): plt.subplot(331 + i) plt.axis('off') plt.imshow(upscale(np.squeeze(noised_data[i])), cmap='gray') # upscale for plotting plt.show() print('GENERATED') for i in range(9): pred = generator.predict(noised_data[i:i+1], verbose=0) plt.subplot(331 + i) plt.axis('off') plt.imshow(upscale(np.squeeze(pred[0])), cmap='gray') # upscale to avoid plotting errors plt.show() print('ORIGINAL') for i in range(9): plt.subplot(331 + i) plt.axis('off') plt.imshow(upscale(np.squeeze(original[i])), cmap='gray') # upscale for plotting plt.show() The output of this function is as follows: Plotting the training – part 2 Let's define another function that plots the images generated during each epoch. To reflect the difference, we will also include the original and the masked/noised images in the plot. The top row contains the original images, the middle row contains the masked images, and the bottom row contains the generated images. The plot has 12 rows with the sequence, row 1 - original, row 2 - masked, row3 - generated, row 4 - original, row5 - masked,..., row 12 - generated. Let's take a look at the code for the same: def plot_generated_images_combined(original, noised_data, generator): rows, cols = 4, 12 num = rows * cols image_size = 28 generated_images = generator.predict(noised_data[0:num]) imgs = np.concatenate([original[0:num], noised_data[0:num], generated_images]) imgs = imgs.reshape((rows * 3, cols, image_size, image_size)) imgs = np.vstack(np.split(imgs, rows, axis=1)) imgs = imgs.reshape((rows * 3, -1, image_size, image_size)) imgs = np.vstack([np.hstack(i) for i in imgs]) imgs = upscale(imgs) plt.figure(figsize=(8,16)) plt.axis('off') plt.title('Original Images: top rows, ' 'Corrupted Input: middle rows, ' 'Generated Images: bottom rows') plt.imshow(imgs, cmap='gray') plt.show() The output is as follows: Training loop Now we are at the most important part of the code; the part where all of the functions we previously defined will be used. The following are the steps: Load the generator by calling the img_generator() function. Load the discriminator by calling the img_discriminator() function and compile it with the binary cross-entropy loss and optimizer as optimizer_d, which we have defined under the hyperparameters section. Feed the generator and the discriminator to the dcgan() function and compile it with the binary cross-entropy loss and optimizer as optimizer_g, which we have defined under the hyperparameters section. Create a new batch of original images and masked images. Generate new fake images by feeding the batch of masked images to the generator. Concatenate the original and generated images so that the first 128 images are all original and the next 128 images are all fake. It is important that you do not shuffle the data here, otherwise it will be hard to train. Label the generated images as 0 and original images as 0.9 instead of 1. This is one-sided label smoothing on the original images. The reason for using label smoothing is to make the network resilient to adversarial examples. It's called one-sided because we are smoothing labels only for the real images. Set discriminator.trainable to True to enable training of the discriminator and feed this set of 256 images and their corresponding labels to the discriminator for classification. Now, set discriminator.trainable to False and feed a new batch of 128 masked images labeled as 1 to the GAN (DCGAN) for classification. It is important to set discriminator.trainable to False to make sure the discriminator is not getting trained while training the generator. Repeat steps 4 through 7 for the desired number of epochs. We have placed the plot_generated_images_combined() function and the generated_images_plot() function to  get a plot generated by both functions after the first iteration in the first epoch and after the end of each epoch. Feel free to place these plot functions according to the frequency of plots you need displayed: def train(X_train, noised_train_data, input_shape, smooth_real, epochs, batch_size, optimizer_g, optimizer_d): # define two empty lists to store the discriminator # and the generator losses discriminator_losses = [] generator_losses = [] # Number of iteration possible with batches of size 128 iterations = X_train.shape[0] // batch_size # Load the generator and the discriminator generator = img_generator(input_shape) discriminator = img_discriminator(input_shape) # Compile the discriminator with binary_crossentropy loss discriminator.compile(loss='binary_crossentropy',optimizer=optimizer_d) # Feed the generator and the discriminator to the function dcgan # to form the DCGAN architecture gan = dcgan(discriminator, generator, input_shape) # Compile the DCGAN with binary_crossentropy loss gan.compile(loss='binary_crossentropy', optimizer=optimizer_g) for i in range(epochs): print ('Epoch %d' % (i+1)) # Use tqdm to get an estimate of time remaining for j in tqdm(range(1, iterations+1)): # batch of original images (batch = batchsize) original = X_train[np.random.randint(0, X_train.shape[0], size=batch_size)] # batch of noised images (batch = batchsize) noise = noised_train_data[np.random.randint(0, noised_train_data.shape[0], size=batch_size)] # Generate fake images generated_images = generator.predict(noise) # Labels for generated data dis_lab = np.zeros(2*batch_size) # data for discriminator dis_train = np.concatenate([original, generated_images]) # label smoothing for original images dis_lab[:batch_size] = smooth_real # Train discriminator on original images discriminator.trainable = True discriminator_loss = discriminator.train_on_batch(dis_train, dis_lab) # save the losses discriminator_losses.append(discriminator_loss) # Train generator gen_lab = np.ones(batch_size) discriminator.trainable = False sample_indices = np.random.randint(0, X_train.shape[0], size=batch_size) original = X_train[sample_indices] noise = noised_train_data[sample_indices] generator_loss = gan.train_on_batch(noise, gen_lab) # save the losses generator_losses.append(generator_loss) if i == 0 and j == 1: print('Iteration - %d', j) generated_images_plot(original, noise, generator) plot_generated_images_combined(original, noise, generator) print("Discriminator Loss: ", discriminator_loss,\ ", Adversarial Loss: ", generator_loss) # training plot 1 generated_images_plot(original, noise, generator) # training plot 2 plot_generated_images_combined(original, noise, generator) # plot the training losses plt.figure() plt.plot(range(len(discriminator_losses)), discriminator_losses, color='red', label='Discriminator loss') plt.plot(range(len(generator_losses)), generator_losses, color='blue', label='Adversarial loss') plt.title('Discriminator and Adversarial loss') plt.xlabel('Iterations') plt.ylabel('Loss (Adversarial/Discriminator)') plt.legend() plt.show() return generator generator = train(X_train, noised_train_data, input_shape, smooth_real, epochs, batch_size, optimizer_g, optimizer_d) The output is as follows:  Generated images plotted with training plots at the end of the first iteration of epoch 1              Generated images plotted with training plots at the end of epoch 2              Generated images plotted with training plots at the end of epoch 5      Plot of the discriminator and adversarial loss during training Predictions CNN classifier predictions on the noised and generated images We will call the generator on the masked MNIST test data to generate images, that is, fill in the missing part of the digits: # restore missing parts of the digit with the generator gen_imgs_test = generator.predict(noised_test_data) Then, we will pass the generated MNIST digits to the digit classifier we have modeled already: # predict on the restored/generated digits gen_pred_lab = mnist_model.predict_classes(gen_imgs_test) print('The model model accuracy on the generated images is:',np.mean(gen_pred_lab==y_test)*100) The MNIST CNN classifier is 87.82% accurate on the generated data. The following is a plot showing 10 generated images by the generator, the actual label of the generated image, and the label predicted by the digit classifier after processing the generated image: # plot of 10 generated images and their predicted label fig=plt.figure(figsize=(8, 4)) plt.title('Generated Images') plt.axis('off') columns = 5 rows = 2 for i in range(0, rows*columns): fig.add_subplot(rows, columns, i+1) plt.title('Act: %d, Pred: %d'%(gen_pred_lab[i],y_test[i])) # label plt.axis('off') # turn off axis plt.imshow(upscale(np.squeeze(gen_imgs_test[i])), cmap='gray') # gray scale plt.show() The output is as follows: The Jupyter Notebook code files for the preceding DCGAN MNIST inpainting can be found at GitHub. Use the Jupyter Notebook code files for the DCGAN Fashion MNIST inpainting can be found. Summary We built a deep convolution GAN in Keras on handwritten MNIST digits and understood the function of the generator and the discriminator component of the GAN. We defined key hyperparameters, as well as, in some places, reasoned with why we used what we did. Finally, we tested the GAN's performance on unseen data and determined that we succeeded in achieving our goals. To understand insightful projects to master deep learning and neural network architectures using Python and Keras, check out this book  Python Deep Learning Projects. Getting started with Web Scraping using Python [Tutorial] Google researchers introduce JAX: A TensorFlow-like framework for generating high-performance code from Python and NumPy machine learning programs Google releases Magenta studio beta, an open source python machine learning library for music artists
Read more
  • 0
  • 0
  • 14675

article-image-creating-and-loading-a-webassembly-module-with-emscriptens-glue-code-tutorial
Prasad Ramesh
04 Jan 2019
10 min read
Save for later

Creating and loading a WebAssembly module with Emscripten's glue code [Tutorial]

Prasad Ramesh
04 Jan 2019
10 min read
With simple C code you can test the compiler without having to accommodate for included libraries or WebAssembly's limitations. We can overcome some of the limitations of WebAssembly in C / C++ code with minimal performance loss by utilizing some of Emscripten's capabilities. In this tutorial, we'll cover the compilation and loading steps of a WebAssembly module that correspond with the use of Emscripten's glue code. The code for this tutorial is available on GitHub. This article is an excerpt from a book written by Mike Rourke titled Learn WebAssembly. In this book, you will learn how to wield WebAssembly to break through the current barriers of web development and build an entirely new class of performant applications. Compiling C with Emscripten glue code By passing certain flags to the emcc command, we can output JavaScript glue code alongside the .wasm file as well as an HTML file to handle the loading process. In this section, we're going to write a complex C program and compile it with the output options that Emscripten offers. Writing the example C code Emscripten offers a lot of extra functionality that enables us to interact with our C and C++ code with JavaScript and vice versa. Some of these capabilities are Emscripten-specific and don't correspond to the Core Specification or its APIs. In our first example, we'll take advantage of one of Emscripten's ported libraries and a function provided by Emscripten's API. The following program uses a Simple DirectMedia Layer (SDL2) to move a rectangle diagonally across a canvas in an infinite loop. It was taken from https://github.com/timhutton/sdl-canvas-wasm, but I converted it from C++ to C and modified the code slightly. The code for this section is located in the /chapter-05-create-load-module folder of the learn-webassembly repository. Follow the following instructions to compile C with Emscripten. Create a folder in your /book-examples folder named /chapter-05-create-load-module. Create a new file in this folder named with-glue.c and populate it with the following contents: /* * Converted to C code taken from: * https://github.com/timhutton/sdl-canvas-wasm * Some of the variable names and comments were also * slightly updated. */ #include <SDL2/SDL.h> #include <emscripten.h> #include <stdlib.h> // This enables us to have a single point of reference // for the current iteration and renderer, rather than // have to refer to them separately. typedef struct Context { SDL_Renderer *renderer; int iteration; } Context; /* * Looping function that draws a blue square on a red * background and moves it across the <canvas>. */ void mainloop(void *arg) { Context *ctx = (Context *)arg; SDL_Renderer *renderer = ctx->renderer; int iteration = ctx->iteration; // This sets the background color to red: SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); SDL_RenderClear(renderer); // This creates the moving blue square, the rect.x // and rect.y values update with each iteration to move // 1px at a time, so the square will move down and // to the right infinitely: SDL_Rect rect; rect.x = iteration; rect.y = iteration; rect.w = 50; rect.h = 50; SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); SDL_RenderFillRect(renderer, &rect); SDL_RenderPresent(renderer); // This resets the counter to 0 as soon as the iteration // hits the maximum canvas dimension (otherwise you'd // never see the blue square after it travelled across // the canvas once). if (iteration == 255) { ctx->iteration = 0; } else { ctx->iteration++; } } int main() { SDL_Init(SDL_INIT_VIDEO); SDL_Window *window; SDL_Renderer *renderer; // The first two 255 values represent the size of the <canvas> // element in pixels. SDL_CreateWindowAndRenderer(255, 255, 0, &window, &renderer); Context ctx; ctx.renderer = renderer; ctx.iteration = 0; // Call the function repeatedly: int infinite_loop = 1; // Call the function as fast as the browser wants to render // (typically 60fps): int fps = -1; // This is a function from emscripten.h, it sets a C function // as the main event loop for the calling thread: emscripten_set_main_loop_arg(mainloop, &ctx, fps, infinite_loop); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return EXIT_SUCCESS; } The emscripten_set_main_loop_arg() toward the end of the main() function is available because we included emscripten.h at the top of the file. The variables and functions prefixed with SDL_ are available because of the #include <SDL2/SDL.h> at the top of the file. If you're seeing a squiggly red error line under the <SDL2/SDL.h> statement, you can disregard it. It's due to SDL's include path not being present in your c_cpp_properties.json file. Compiling the example C code Now that we have our C code written, we'll need to compile it. One of the required flags you must pass to the emcc command is -o <target>, where <target> is the path to the desired output file. The extension of that file will do more than just output that file; it impacts some of the decisions the compiler makes. The following table, taken from Emscripten's emcc documentation at http://kripken.github.io/emscripten-site/docs/tools_reference/emcc.html#emcc-o-target, defines the generated output types based on the file extension specified: ExtensionOutput<name>.js JavaScript glue code (and .wasm if the s WASM=1 flag is specified). <name>.html HTML and separate JavaScript file (<name>.js). Having the separate JavaScript file improves page load time. <name>.bc LLVM bitcode (default). <name>.o LLVM bitcode (same as .bc). <name>.wasm Wasm file only. You can disregard the .bc and .o file extensions—we won't need to output LLVM bitcode. The .wasm extension isn't on the emcc Tools Reference page, but it is a valid option if you pass the correct compiler flags. These output options factor into the C/C++ code we write. Outputting HTML with glue code If you specify an HTML file extension (for example, -o with-glue.html) for the output, you'll end up with a with-glue.html, with-glue.js, and with-glue.wasm file (assuming you also specified -s WASM=1). If you have a main() function in the source C/C++ file, it'll execute that function as soon as the HTML loads. Let's compile our example C code to see this in action. To compile it with the HTML file and JavaScript glue code, cd into the /chapter-05-create-load-module folder and run the following command: emcc with-glue.c -O3 -s WASM=1 -s USE_SDL=2 -o with-glue.html The first time you run this command, Emscripten is going to download and build the SDL2 library. It could take several minutes to complete this, but you'll only need to wait once. Emscripten caches the library so subsequent builds will be much faster. Once the build is complete, you'll see three new files in the folder: HTML, JavaScript, and Wasm files. Run the following command to serve the file locally: serve -l 8080 If you open your browser up to http://127.0.0.1:8080/with-glue.html, you should see the following: The blue rectangle should be moving diagonally from the upper-left corner of the red rectangle to the lower-right. Since you specified a main() function in the C file, Emscripten knows it should execute it right away. If you open up the with-glue.html file in VS code and scroll to the bottom of the file, you will see the loading code. You won't see any references to the WebAssembly object; that's being handled in the JavaScript glue code file. Outputting glue code with no HTML The loading code that Emscripten generates in the HTML file contains error handling and other helpful functions to ensure the module is loading before executing the main() function. If you specify .js for the extension of the output file, you'll have to create an HTML file and write the loading code yourself. In the next section, we're going to dig into the loading code in more detail. Loading the Emscripten module Loading and interacting with a module that utilizes Emscripten's glue code is considerably different from WebAssembly's JavaScript API. This is because Emscripten provides additional functionality for interacting with the JavaScript code. In this section, we're going to discuss the loading code that Emscripten provides when outputting an HTML file and review the process for loading an Emscripten module in the browser. Pre-generated loading code If you specify -o <target>.html when running the emcc command, Emscripten generates an HTML file and automatically adds code to load the module to the end of the file. Here's what the loading code in the HTML file looks like with the contents of each Module function excluded: var statusElement = document.getElementById('status'); var progressElement = document.getElementById('progress'); var spinnerElement = document.getElementById('spinner'); var Module = { preRun: [], postRun: [], print: (function() {...})(), printErr: function(text) {...}, canvas: (function() {...})(), setStatus: function(text) {...}, totalDependencies: 0, monitorRunDependencies: function(left) {...} }; Module.setStatus('Downloading...'); window.onerror = function(event) { Module.setStatus('Exception thrown, see JavaScript console'); spinnerElement.style.display = 'none'; Module.setStatus = function(text) { if (text) Module.printErr('[post-exception status] ' + text); }; }; The functions within the Module object are present to detect and address errors, monitor the loading status of the Module, and optionally execute some functions before or after the run() method from the corresponding glue code file executes. The canvas function, shown in the following snippet, returns the <canvas> element from the DOM that was specified in the HTML file before the loading code: canvas: (function() { var canvas = document.getElementById('canvas'); canvas.addEventListener( 'webglcontextlost', function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false ); return canvas; })(), This code is convenient for detecting errors and ensuring the Module is loaded, but for our purposes, we won't need to be as verbose. Writing custom loading code Emscripten's generated loading code provides helpful error handling. If you're using Emscripten's output in production, I would recommend that you include it to ensure you're handling errors correctly. However, we don't actually need all the code to utilize our Module. Let's write some much simpler code and test it out. First, let's compile our C file down to glue code with no HTML output. To do that, run the following command: emcc with-glue.c -O3 -s WASM=1 -s USE_SDL=2 -s MODULARIZE=1 -o custom-loading.js The -s MODULARIZE=1 compiler flag allows us to use a Promise-like API to load our Module. Once the compilation is complete, create a file in the /chapter-05-create-load-module folder named custom-loading.html and populate it with the following contents: The loading code is now using ES6's arrow function syntax for the canvas loading function, which reduces the lines of code required. Start your local server by running the serve command within the /chapter-05-create-load-module folder: serve -l 8080 When you navigate to http://127.0.0.1:8080/custom-loading.html in your browser, you should see this: Of course, the function we're running isn't very complex, but it demonstrates the bare-bones requirements for loading Emscripten's Module. For now just be aware that the loading process is different from WebAssembly, which we'll cover in the next section. In this article, we looked at compiling C with Emscripten glue code and loading the Emscripten module. We also covered writing example C code and custom code. To know more about compiling C without the glue code, instantiating a Wasm file, installing the required dependencies for the actions performed here, and know build WebAssembly applications, check out the book Learn WebAssembly. How has Rust and WebAssembly evolved in 2018 WebAssembly – Trick or Treat? Mozilla shares plans to bring desktop applications, games to WebAssembly and make deeper inroads for the future web
Read more
  • 0
  • 0
  • 39688

article-image-the-elements-of-webassembly-wat-and-wasm-explained-tutorial
Prasad Ramesh
03 Jan 2019
9 min read
Save for later

The elements of WebAssembly - Wat and Wasm, explained [Tutorial]

Prasad Ramesh
03 Jan 2019
9 min read
In this tutorial, we will dig into the elements that correspond to the official specifications created by the WebAssembly Working Group. We will examine the Wat and the binary format in greater detail to gain a better understanding of how they relate to modules. This article is an excerpt from a book written by Mike Rourke titled Learn WebAssembly. In this book, you will learn how to build web applications with native performance using Wasm and C/C++<mark. Common structure and abstract syntax Before getting into the nuts and bolts of these formats, it's worth mentioning how these are related within the Core Specification. The following diagram is a visual representation of the table of contents (with some sections excluded for clarity): As you can see, the Text Format and Binary Format sections contain subsections for Values, Types, Instructions, and Modules that correlate with the Structure section. Consequently, much of what we cover in the next section for the text format have direct corollaries with the binary format. With that in mind, let's dive into the text format. Wat The Text Format section of the Core Specification provides technical descriptions for common language concepts such as values, types, and instructions. These are important concepts to know and understand if you're planning on building tooling for WebAssembly, but not necessary if you just plan on using it in your applications. That being said, the text format is an important part of WebAssembly, so there are concepts you should be aware of. In this section, we will dig into some of the details of the text format and highlight important points from the Core Specification. Definitions and S-expressions To understand Wat, let's start with the first sentence of the description taken directly from the WebAssembly Core Specification: "The textual format for WebAssembly modules is a rendering of their abstract syntax into S-expressions." So what are symbolic expressions (S-expressions)? S-expressions are notations for nested list (tree-structured) data. Essentially, they provide a simple and elegant way to represent list-based data in textual form. To understand how textual representations of nested lists map to a tree structure, let's extrapolate the tree structure from an HTML page. The following example contains a simple HTML page and the corresponding tree structure diagram. A simple HTML page: The corresponding tree structure is: Even if you've never seen a tree structure before, it's still clear to see how the HTML maps to the tree in terms of structure and hierarchy. Mapping HTML elements is relatively simple because it's a markup language with well-defined tags and no actual logic. Wat represents modules that can have multiple functions with varying parameters. To demonstrate the relationship between source code, Wat, and the corresponding tree structure, let's start with a simple C function that adds 2 to the number that is passed in as a parameter: Here is a C function that adds 2 to the num argument passed in and returns the result: int addTwo(int num) { return num + 2; } Converting the addTwo function to valid Wat produces this result: (module (table 0 anyfunc) (memory $0 1) (export "memory" (memory $0)) (export "addTwo" (func $addTwo)) (func $addTwo (; 0 ;) (param $0 i32) (result i32) (i32.add (get_local $0) (i32.const 2) ) ) ) The Structure section defines each of these concepts in the context of an abstract syntax. The Text Format section of the specification corresponds with these concepts as well, and you can see them defined by their keywords in the preceding snippet (func, memory, table). Tree Structure: The entire tree would be too large to fit on a page, so this diagram is limited to the first five lines of the Wat source text. Each filled-in dot represents a list node (or the contents of a set of parentheses). As you can see, code written in s-expressions can be clearly and concisely expressed in a tree structure, which is why s-expressions were chosen for WebAssembly's text format. Values, types, and instructions Although detailed coverage of the Text Format section of the Core Specification is out of the scope of this text, it's worth demonstrating how some of the language concepts map to the corresponding Wat. The following diagram demonstrates these mappings in a sample Wat snippet. The C code that this was compiled from represents a function that takes a word as a parameter and returns the square root of the character count: If you intend on writing or editing Wat, note that it supports block and line comments. The instructions are split up into blocks and consist of setting and getting memory associated with variables with valid types. You are able to control the flow of logic using if statements and loops are supported using the loop keyword. Role in the development process The text format allows for the representation of a binary Wasm module in textual form. This has some profound implications with regard to the ease of development and debugging. Having a textual representation of a WebAssembly module allows developers to view the source of a loaded module in a browser, which eliminates the black-box issues that inhibited the adoption of NaCl. It also allows for tooling to be built around troubleshooting modules. The official website describes the use cases that drove the design of the text format: • View Source on a WebAssembly module, thus fitting into the Web (where every source can be viewed) in a natural way. • Presentation in browser development tools when source maps aren't present (which is necessarily the case with the Minimum Viable Product (MVP)). • Writing WebAssembly code directly for reasons including pedagogical, experimental, debugging, optimization, and testing of the spec itself. The last item in the list reflects that the text format isn't intended to be written by hand in the course of normal development, but rather generated from a tool like Emscripten. You probably won't see or manipulate any .wat files when you're generating modules, but you may be viewing them in a debugging context. Not only is the text format valuable with regards to debugging, but having this intermediate format reduces the amount of reliance on a single tool for compilation. Several different tools currently exist to consume and emit this s-expression syntax, some of which are used by Emscripten to compile your code down to a .wasm file. Binary format and the module file (Wasm) The Binary Format section of the Core Specification provides the same level of detail with regard to language concepts as the Text format section. In this section, we will briefly cover some high-level details about the binary format and discuss the various sections that make up a Wasm module. Definition and module overview The binary format is defined as a dense linear encoding of the abstract syntax. Without getting too technical, that essentially means it's an efficient form of binary that allows for fast decoding, small file size, and reduced memory usage. The file representation of the binary format is a .wasm file. The Values, Types, and Instructions subsections of the Core Specification for the binary format correlate directly to the Text Format section. Each of these concepts is covered in the context of encoding. For example, according to the specification, the Integer types are encoded using the LEB128 variable-length integer encoding, in either unsigned or signed variant. These are important details to know if you wish to develop tooling for WebAssembly, but not necessary if you just plan on using it on your website. The Structure, Binary Format, and Text Format (wat) sections of the Core Specification have a Module subsection. We didn't cover aspects of the module in the previous section because it's more prudent to describe them in the context of a binary. The official WebAssembly site offers the following description for a module: "The distributable, loadable, and executable unit of code in WebAssembly is called a module. At runtime, a module can be instantiated with a set of import values to produce an instance, which is an immutable tuple referencing all the state accessible to the running module." Module sections A module is made up of several sections, some of which you'll be interacting with through the JavaScript API: Imports (import) are elements that can be accessed within the module and can be one of the following: Function, which can be called inside the module using the call operator Global, which can be accessed inside the module via the global operators Linear Memory, which can be accessed inside the module via the memory operators Table, which can be accessed inside the module using call_indirect Exports (export) are elements that can be accessed by the consuming API (that is, called by a JavaScript function) Module start function (start) is called after the module instance is initialized Global (global) contains the internal definition of global variables Linear memory (memory) contains the internal definition of linear memory with an initial memory size and optional maximum size Data (data) contains an array of data segments which specify the initial contents of fixed ranges of a given memory Table (table) is a linear memory whose elements are opaque values of a particular table element type: In the MVP, its primary purpose is to implement indirect function calls in C/C++ Elements (elements) is a section that allows a module to initialize the elements of any import or internally defined table with any other definition in the module Function and code: The function section declares the signatures of each internal function defined in the module The code section contains the function body of each function declared by the function section Some of the keywords (import, export, and so on) should look familiar; they're present in the contents of the Wat file in the previous section. WebAssembly's components follow a logical mapping that directly correspond to the APIs  (for example, you pass a memory and table instance into JavaScript's WebAssembly.instantiate() function). Your primary interaction with a module in binary format will be through these APIs. In this tutorial, we looked at the WebAssembly modules Wat and Wasm. We covered Wat definitions, values, types, instructions, and its role. We looked at Wasm overview and its module sections. To know more about another element of WebAssembly, the JavaScript API and build applications on WebAssembly check out the book Learn WebAssembly. How has Rust and WebAssembly evolved in 2018 WebAssembly – Trick or Treat? Mozilla shares plans to bring desktop applications, games to WebAssembly and make deeper inroads for the future web
Read more
  • 0
  • 0
  • 60935
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 €18.99/month. Cancel anytime
article-image-18-people-in-tech-every-programmer-and-software-engineer-needs-to-follow-in-2019
Richard Gall
02 Jan 2019
9 min read
Save for later

18 people in tech every programmer and software engineer needs to follow in 2019

Richard Gall
02 Jan 2019
9 min read
After a tumultuous 2018 in tech, it's vital that you surround yourself with a variety of opinions and experiences in 2019 if you're to understand what the hell is going on. While there are thousands of incredible people working in tech, I've decided to make life a little easier for you by bringing together 18 of the best people from across the industry to follow on Twitter. From engineers at Microsoft and AWS, to researchers and journalists, this list is by no means comprehensive but it does give you a wide range of people that have been influential, interesting, and important in 2018. (A few of) the best people in tech on Twitter April Wensel (@aprilwensel) April Wensel is the founder of Compassionate Coding, an organization that aims to bring emotional intelligence and ethics into the tech industry. In April 2018 Wensel wrote an essay arguing that "it's time to retire RTFM" (read the fucking manual). The essay was well received by many in the tech community tired of a culture of ostensible caustic machismo and played a part in making conversations around community accessibility an important part of 2018. Watch her keynote at NodeJS Interactive: https://www.youtube.com/watch?v=HPFuHS6aPhw Liz Fong-Jones (@lizthegrey) Liz Fong-Jones is an SRE and Dev Advocate at Google Cloud Platform, but over the last couple of years she has become an important figure within tech activism. First helping to create the NeverAgain pledge in response to the election of Donald Trump in 2016, then helping to bring to light Google's fraught internal struggle over diversity, Fong-Jones has effectively laid the foundations for the mainstream appearance of tech activism in 2018. In an interview with Fast Company, Fong-Jones says she has accepted her role as a spokesperson for the movement that has emerged, but she's committed to helping to "equipping other employees to fight for change in their workplaces–whether at Google or not –so that I’m not a single point of failure." Ana Medina (@Ana_M_Medina) Ana Medina is a chaos engineer at Gremlin. Since moving to the chaos engineering platform from Uber (where she was part of the class action lawsuit against the company), Medina has played an important part in explaining what chaos engineering looks like in practice all around the world. But she is also an important voice in discussions around diversity and mental health in the tech industry - if you get a chance to her her talk, make sure you take the chance, and if you don't, you've still got Twitter... Sarah Drasner (@sarah_edo) Sarah Drasner does everything. She's a Developer Advocate at Microsoft, part of the VueJS core development team, organizer behind Concatenate (a free conference for Nigerian developers), as well as an author too. https://twitter.com/sarah_edo/status/1079400115196944384 Although Drasner specializes in front end development and JavaScript, she's a great person to follow on Twitter for her broad insights on how we learn and evolve as software developers. Do yourself a favour and follow her. Mark Imbriaco (@markimbriaco) Mark Imbriaco is the technical director at Epic Games. Given the company's truly, er, epic year thanks to Fortnite, Imbriaco can offer an insight on how one of the most important and influential technology companies on the planet are thinking. Corey Quinn (@QuinnyPig) Corey Quinn is an AWS expert. As the brain behind the Last Week in AWS newsletter and the voice behind the Screaming in the Cloud podcast (possibly the best cloud computing podcast on the planet), he is without a doubt the go-to person if you want to know what really matters in cloud. The range of guests that Quinn gets on the podcast is really impressive, and sums up his online persona: open, engaged, and always interesting. Yasmine Evjen (@YasmineEvjen) Yasmine Evjen is a Design Advocate at Google. That means that she is not only one of the minds behind Material Design, she is also someone that is helping to demonstrate the importance of human centered design around the world. As the presenter of Centered, a web series by the Google Design team about the ways human centered design is used for a range of applications. If you haven't seen it, it's well worth a watch. https://www.youtube.com/watch?v=cPBXjtpGuSA&list=PLJ21zHI2TNh-pgTlTpaW9kbnqAAVJgB0R&index=5&t=0s Suz Hinton (@noopkat) Suz Hinton works on IoT programs at Microsoft. That's interesting in itself, but when she's not developing fully connected smart homes (possibly), Hinton also streams code tutorials on Twitch (also as noopkat). Chris Short (@ChrisShort) If you want to get the lowdown on all things DevOps, you could do a lot worse than Chris Short. He boasts outstanding credentials - he's a CNCF ambassador, has experience with Red Hat and Ansible - but more importantly is the quality of his insights. A great place to begin is with DevOpsish, a newsletter Short produces, which features some really valuable discussions on the biggest issues and talking points in the field. Dan Abramov (@dan_abramov) Dan Abramov is one of the key figures behind ReactJS. Along with @sophiebits,@jordwalke, and @sebmarkbage, Abramov is quite literally helping to define front end development as we know it. If you're a JavaScript developer, or simply have any kind of passing interest in how we'll be building front ends over the next decade, he is an essential voice to have on your timeline. As you'd expect from someone that has helped put together one of the most popular JavaScript libraries in the world, Dan is very good at articulating some of the biggest challenges we face as developers and can provide useful insights on how to approach problems you might face, whether day to day or career changing. Emma Wedekind (@EmmaWedekind) As well as working at GoTo Meeting, Emma Wedekind is the founder of Coding Coach, a platform that connects developers to mentors to help them develop new skills. This experience makes Wedekind an important authority on developer learning. And at a time when deciding what to learn and how to do it can feel like such a challenging and complex process, surrounding yourself with people taking those issues seriously can be immensely valuable. Jason Lengstorf (@jlengstorf) Jason Lengstorf is a Developer Advocate at GatsbyJS (a cool project that makes it easier to build projects with React). His writing - on Twitter and elsewhere - is incredibly good at helping you discover new ways of working and approaching problems. Bridget Kromhout (@bridgetkromhout) Bridget Kromhout is another essential voice in cloud and DevOps. Currently working at Microsoft as Principal Cloud Advocate, Bridget also organizes DevOps Days and presents the Arrested DevOps podcast with Matty Stratton and Trevor Hess. Follow Bridget for her perspective on DevOps, as well as her experience in DevRel. Ryan Burgess (@burgessdryan) Netflix hasn't faced the scrutiny of many of its fellow tech giants this year, which means it's easy to forget the extent to which the company is at the cutting edge of technological innovation. This is why it's well worth following Ryan Burgess - as an engineering manager he's well placed to provide an insight on how the company is evolving from a tech perspective. His talk at Real World React on A/B testing user experiences is well worth watching: https://youtu.be/TmhJN6rdm28 Anil Dash (@anildash) Okay, so chances are you probably already follow Anil Dash - he does have half a million followers already, after all - but if you don't follow him, you most definitely should. Dash is a key figure in new media and digital culture, but he's not just another thought leader, he's someone that actually understands what it takes to actually build this stuff. As CEO of Glitch, a platform for building (and 'remixing') cool apps, he's having an impact on the way developers work and collaborate. 6 years ago, Dash wrote an essay called 'The Web We Lost'. In it, he laments how the web was becoming colonized by a handful of companies who built the key platforms on which we communicate and engage with one another online. Today, after a year of protest and controversy, Dash's argument is as salient as ever - it's one of the reasons it's vital that we listen to him. Jessie Frazelle (@jessfraz) Jessie Frazelle is a bit of a superstar. Which shouldn't really be that surprising - she's someone that seems to have a natural ability to pull things apart and put them back together again and have the most fun imaginable while doing it. Formerly part of the core Docker team, Frazelle now works at GitHub, where her knowledge and expertise is helping to develop the next Microsoft-tinged chapter in GitHub's history. I was lucky enough to see Jessie speak at ChaosConf in September - check out her talk: https://youtu.be/1hhVS4pdrrk Rachel Coldicutt (@rachelcoldicutt) Rachel Coldicutt is the CEO of Doteveryone, a think tank based in the U.K. that champions responsible tech. If you're interested in how technology interacts with other aspects of society and culture, as well as how it is impacting and being impacted by policymakers, Coldicutt is a vital person to follow. Kelsey Hightower (@kelseyhightower) Kelsey Hightower is another superstar in the tech world - when he talks, you need to listen. Hightower currently works at Google Cloud, but he spends a lot of time at conferences evangelizing for more effective cloud native development. https://twitter.com/mattrickard/status/1073285888191258624 If you're interested in anything infrastructure or cloud related, you need to follow Kelsey Hightower. Who did I miss? That's just a list of a few people in tech I think you should follow in 2019 - but who did I miss? Which accounts are essential? What podcasts and newsletters should we subscribe to?
Read more
  • 0
  • 0
  • 23868

article-image-all-of-my-engineering-teams-have-a-machine-learning-feature-on-their-roadmap-will-ballard-talks-artificial-intelligence-in-2019-interview
Packt Editorial Staff
02 Jan 2019
3 min read
Save for later

“All of my engineering teams have a machine learning feature on their roadmap” - Will Ballard talks artificial intelligence in 2019 [Interview]

Packt Editorial Staff
02 Jan 2019
3 min read
The huge advancements of deep learning and artificial intelligence were perhaps the biggest story in tech in 2018. But we wanted to know what the future might hold - luckily, we were able to speak to Packt author Will Ballard about what they see as in store for artificial in 2019 and beyond. Will Ballard is the chief technology officer at GLG, responsible for engineering and IT. He was also responsible for the design and operation of large data centers that helped run site services for customers including Gannett, Hearst Magazines, NFL, NPR, The Washington Post, and Whole Foods. He has held leadership roles in software development at NetSolve (now Cisco), NetSpend, and Works (now Bank of America). Explore Will Ballard's Packt titles here. Packt: What do you think the biggest development in deep learning / AI was in 2018? Will Ballard: I think attention models beginning to take the place of recurrent networks is a pretty impressive breakout on the algorithm side. In Packt’s 2018 Skill Up survey, developers across disciplines and job roles identified machine learning as the thing they were most likely to be learning in the coming year. What do you think of that result? Do you think machine learning is becoming a mandatory multidiscipline skill, and why? Almost all of my engineering teams have an active, or a planned machine learning feature on their roadmap. We’ve been able to get all kinds of engineers with different backgrounds to use machine learning -- it really is just another way to make functions -- probabilistic functions -- but functions. What do you think the most important new deep learning/AI technique to learn in 2019 will be, and why? In 2019 -- I think it is going to be all about PyTorch and TensorFlow 2.0, and learning how to host these on cloud PaaS. The benefits of automated machine learning and metalearning How important do you think automated machine learning and metalearning will be to the practice of developing AI/machine learning in 2019? What benefits do you think they will bring? Even ‘simple’ automation techniques like grid search and running multiple different algorithms on the same data are big wins when mastered. There is almost no telling which model is ‘right’ till you try it, so why not let a cloud of computers iterate through scores of algorithms and models to give you the best available answer? Artificial intelligence and ethics Do you think ethical considerations will become more relevant to developing AI/machine learning algorithms going forwards? If yes, how do you think this will be implemented? I think the ethical issues are important on outcomes, and on how models are used, but aren’t the place of algorithms themselves. If a developer was looking to start working with machine learning/AI, what tools and software would you suggest they learn in 2019? Python and PyTorch.
Read more
  • 0
  • 0
  • 30007

article-image-introduction-to-open-shortest-path-first-ospf-tutorial
Amrata Joshi
02 Jan 2019
14 min read
Save for later

Introduction to Open Shortest Path First (OSPF) [Tutorial]

Amrata Joshi
02 Jan 2019
14 min read
The OSPF interior routing protocol is a very popular protocol in enterprise networks. OSPF does a very good job in calculating cost values to choose the Shortest Path First to its destinations. OSPF operations can be separated into three categories: Neighbor and adjacency initialization LSA flooding SPF tree calculation This article is an excerpt taken from the book  CCNA Routing and Switching 200-125 Certification Guide by Lazaro (Laz) Diaz. This book covers the understanding of networking using routers and switches, layer 2 technology and its various configurations and connections, VLANS and inter-VLAN routing and more. In this article, we will cover the basics of OSPF, its features and configuration, and much more. Neighbor and adjacency initialization This is the very first part of OSPF operations. The router at this point will allocate memory for this function as well as for the maintenance of both the neighbor and topology tables. Once the router discovers which interfaces are configured with OSPF, it will begin sending hello packets throughout the interface in the hope of finding other routers using OSPF. Let's look at a visual representation: Remember this would be considered a broadcast in between the routers so the election needs to run to choose DR and BDR. 00:03:06: OSPF: DR/BDR election on FastEthernet0/0 00:03:06: OSPF: Elect BDR 10.1.1.5 00:03:06: OSPF: Elect DR 10.1.1.6 00:03:06: OSPF: Elect BDR 10.1.1.5 00:03:06: OSPF: Elect DR 10.1.1.6 00:03:06: DR: 10.1.1.6 (Id) BDR: 10.1.1.5 (Id) One thing to keep in mind is that if you are using Ethernet, as we are, the hello packet timer is set to 10 seconds. If it is not an Ethernet connection, the hello packet timer will be set to 30 seconds. Why is this so important to know? Because the hello packet timer must be identical to its adjacent router or they will never become neighbors. Link State Advertisements and Flooding Before we begin with LSA flooding and how it uses LSUs to create the OSPF routing table, let's elaborate on this term. There is not just one type of LSA either. Let's have a look at the following table: By no means are these the only LSAs that exist. There are 11 LSAs, but for the CCNA, you must know about the ones that I highlighted, do not dismiss the rest. LSA updates are sent via multicast addresses. Depending on the type of network topology you have, that multicast address is used. For the point-to-point networks, the multicast address is 224.0.0.5. In a broadcast environment, 224.0.0.6 is used. But as we get further into OSPF and start discussing DR/BDR routers in a broadcast environment, the DR uses 224.0.0.5 and the BDR uses 224.0.0.6. In any case, remember that these two multicast addresses are used within OSPF. The network topology is created via LSAs updates, for which the information is acquired through LSUs or link state updates. So, OSPF routers, after they have converged, send hellos via LSAs. If any new change happens, it is the job of the LSU to update the LSA of the routers in order to keep routing tables current. Configuring the basics of OSPF You have already had a sneak peek into the configuration of OSPF, but let's take it back to the basics. The following diagram shows the topology: Yes, this is the basic topology, but we will do a dual stack, shown as follows: Configuration of R1: Configuration of R2: Configuration of R3: So, what did we do? We put the IP addresses on each interface and since we are using serial cables, on the DCE side of the cable, we must use the clock rate command and assign the clock rate for synchronization and encapsulation. Then we configured OSPF with basic configuration, which means that all we did was advertise the networks we are attached to using the process ID number, which is local to the router. The complete network ID address we are partly using is a wildcard mask and since this is the first area, we must use area 0. We can verify several ways to use the ping command. Use the sh ip protocols or sh ip route, but let's look at how this would look. Verifying from R1, you will get the following: There are three simple commands that we could use to verify that our configuration of OSPF is correct. One thing you need to know very well is wild card masking, so let me show you a couple of examples: Before we begin, let me you present a very simple way of doing wildcard masking. All you must do is use the constant number 255.255.255.255 and subtract your subnet mask from it: So, as you can plainly see, your mask will determine the wildcard mask. The network ID may look the same but you will have three different wildcard masks. That would be a lot of different hosts pointing to a specific interface. Finally, let's look at another example, which is a subnetted Class A address: It's extremely simple, with no physics needed. So, that was a basic configuration of OSPF, but you can configure OSPF in many ways. I just explained wildcard masking, but remember that zeros need to match exactly, so what can you tell me about the following configuration, using a different topology? R1(config)#router ospf 1 R1(config-router)#net 0.0.0.0 0.0.0.0 area 0 R2(config)#router ospf 2 R2(config-router)#net 10.1.1.6 0.0.0.0 area 0 R2(config-router)#net 10.1.1.9 0.0.0.0 area 0 R2(config-router)#net 2.2.2.2 0.0.0.0 area 0 R3(config)#router ospf 3 R3(config-router)#net 10.1.1.0 0.0.0.255 area 0 R3(config-router)#net 3.3.3.0 0.0.0.255 area 0 We configured OSPF in three different ways, so let's explain each one. In this new topology, we are playing around with the wildcard mask. You can see in the first configuration that when we create the network statement, we use all zeros, 0.0.0.0 0.0.0.0, and then we put in the area number. Using all zeros means matching all interfaces, so any IP address that exists on the router will be matched by OSPF, placed in area 0, and advertised to the neighbor routers. In the second example, when we create our network statement, we put the actual IP address of the interface and then use a wildcard mask of all zeros, 192.168.1.254 0.0.0.0. In this case, OSPF will know exactly what interface is going to participate in the OSPF process, because we are matching exactly each octet. In the last example, the network state created was using the network ID and then we only matched the first three octets and we used 255 on the last octet, which states whatever number. So, OSPF has tremendous flexibility in its configurations, to meet your needs on the network. You just need to know what those needs are. By the way, I hope you spotted that I used a different process ID number on each router. Keep in mind for the CCNA and even most "real-world" networks that the process ID number is only locally significant. The other routers do not care, so this number can be whatever you want it to be. To further prove that the three new ways of configuring OSPF work, here are the routers' output: R1#sh ip route Gateway of last resort is not set 1.0.0.0/32 is subnetted, 1 subnets C 1.1.1.1 is directly connected, Loopback1 2.0.0.0/32 is subnetted, 1 subnets O 2.2.2.2 [110/2] via 10.1.1.6, 18:41:09, FastEthernet0/0 3.0.0.0/32 is subnetted, 1 subnets O 3.3.3.3 [110/3] via 10.1.1.6, 18:41:09, FastEthernet0/0 10.0.0.0/30 is subnetted, 2 subnets O 10.1.1.8 [110/2] via 10.1.1.6, 18:41:09, FastEthernet0/0 C 10.1.1.4 is directly connected, FastEthernet0/0 R1#sh ip protocols Routing Protocol is "ospf 1" Outgoing update filter list for all interfaces is not set Incoming update filter list for all interfaces is not set Router ID 1.1.1.1 Number of areas in this router is 1. 1 normal 0 stub 0 nssa Maximum path: 4 Routing for Networks: 0.0.0.0 255.255.255.255 area 0 Reference bandwidth unit is 100 mbps Routing Information Sources: Gateway Distance Last Update 3.3.3.3 110 18:41:42 2.2.2.2 110 18:41:42 Distance: (default is 110) R1#ping 2.2.2.2 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 2.2.2.2, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 16/20/24 ms R1#ping 3.3.3.3 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 3.3.3.3, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 36/52/72 ms As you can see, I have full connectivity and by looking at my routing table, I am learning about all the routes. But I want to show the differences in the configuration of the network statements for the three routers using the sh ip protocols command: R2#sh ip protocols Routing Protocol is "ospf 2" Outgoing update filter list for all interfaces is not set Incoming update filter list for all interfaces is not set Router ID 2.2.2.2 Number of areas in this router is 1. 1 normal 0 stub 0 nssa Maximum path: 4 Routing for Networks: 2.2.2.2 0.0.0.0 area 0 10.1.1.6 0.0.0.0 area 0 10.1.1.9 0.0.0.0 area 0 Reference bandwidth unit is 100 mbps Routing Information Sources: Gateway Distance Last Update 3.3.3.3 110 18:31:18 1.1.1.1 110 18:31:18 Distance: (default is 110) R3#sh ip protocols Routing Protocol is "ospf 3" Outgoing update filter list for all interfaces is not set Incoming update filter list for all interfaces is not set Router ID 3.3.3.3 Number of areas in this router is 1. 1 normal 0 stub 0 nssa Maximum path: 4 Routing for Networks: 3.3.3.0 0.0.0.255 area 0 10.1.1.0 0.0.0.255 area 0 Reference bandwidth unit is 100 mbps Routing Information Sources: Gateway Distance Last Update 2.2.2.2 110 18:47:13 1.1.1.1 110 18:47:13 Distance: (default is 110) To look at other features that OSPF uses, we are going to explore the passive-interface command. This is very useful in preventing updates being sent out. But be warned, this command works differently with other routing protocols. For example, if you were to configure it on EIGRP, it will not send or receive updates. In OSPF, it simply prevents updates from being sent out, but will receive updates for neighbor routers. It will not update its routing table, so essentially that interface is down. Let's look from the perspective of R2: R2(config-router)#passive-interface f1/0 *Oct 3 04:47:01.763: %OSPF-5-ADJCHG: Process 2, Nbr 1.1.1.1 on FastEthernet1/0 from FULL to DOWN, Neighbor Down: Interface down or detached Almost immediately, it took the F1/0 interface down. What's happening is that the router is not sending any hellos. Let's further investigate by using the debug ip ospf hello command: R2#debug ip ospf hello OSPF hello events debugging is on R2# *Oct 3 04:49:40.319: OSPF: Rcv hello from 3.3.3.3 area 0 from FastEthernet1/1 10.1.1.10 *Oct 3 04:49:40.319: OSPF: End of hello processing R2# *Oct 3 04:49:43.723: OSPF: Send hello to 224.0.0.5 area 0 on FastEthernet1/1 from 10.1.1.9 R2# *Oct 3 04:49:50.319: OSPF: Rcv hello from 3.3.3.3 area 0 from FastEthernet1/1 10.1.1.10 *Oct 3 04:49:50.323: OSPF: End of hello processing R2# *Oct 3 04:49:53.723: OSPF: Send hello to 224.0.0.5 area 0 on FastEthernet1/1 from 10.1.1.9 R2# *Oct 3 04:50:00.327: OSPF: Rcv hello from 3.3.3.3 area 0 from FastEthernet1/1 10.1.1.10 *Oct 3 04:50:00.331: OSPF: End of hello processing It is no longer sending updates out to the F1/0 interface, so let's look at the routing table now and see what networks we know about: R2#sh ip route Gateway of last resort is not set 2.0.0.0/32 is subnetted, 1 subnets C 2.2.2.2 is directly connected, Loopback2 3.0.0.0/32 is subnetted, 1 subnets O 3.3.3.3 [110/2] via 10.1.1.10, 00:05:12, FastEthernet1/1 10.0.0.0/30 is subnetted, 2 subnets C 10.1.1.8 is directly connected, FastEthernet1/1 C 10.1.1.4 is directly connected, FastEthernet1/0 R2#ping 2.2.2.2 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 2.2.2.2, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 1/1/4 ms R2#ping 3.3.3.3 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 3.3.3.3, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 20/24/40 ms So, what are we looking at? We are only learning about the 3.3.3.3 network, which is the loopback address on R3. We have stopped learning about the 1.1.1.1 network, and we do not have connectivity to it. We can ping our own loopback, obviously, and we can ping the loopback on R3. Okay, let's remove the passive interface command and compare the difference: R2(config)#router ospf 2 R2(config-router)#no passive-interface f1/0 R2(config-router)# *Oct 3 04:57:34.343: %OSPF-5-ADJCHG: Process 2, Nbr 1.1.1.1 on FastEthernet1/0 from LOADING to FULL, Loading Done We have now recreated our neighbor relationship with R1 once more. Let's debug again: R2#debug ip ospf hello OSPF hello events debugging is on R2# *Oct 3 05:03:48.527: OSPF: Send hello to 224.0.0.5 area 0 on FastEthernet1/0 from 10.1.1.6 R2# *Oct 3 05:03:50.303: OSPF: Rcv hello from 3.3.3.3 area 0 from FastEthernet1/1 10.1.1.10 *Oct 3 05:03:50.303: OSPF: End of hello processing R2# *Oct 3 05:03:52.143: OSPF: Rcv hello from 1.1.1.1 area 0 from FastEthernet1/0 10.1.1.5 *Oct 3 05:03:52.143: OSPF: End of hello processing R2# *Oct 3 05:03:53.723: OSPF: Send hello to 224.0.0.5 area 0 on FastEthernet1/1 from 10.1.1.9 Once again, we are sending and receiving hellos from R1, so let's ping the loopback on R1, but also look at the routing table: R2#sh ip route Gateway of last resort is not set 1.0.0.0/32 is subnetted, 1 subnets O 1.1.1.1 [110/2] via 10.1.1.5, 00:06:50, FastEthernet1/0 2.0.0.0/32 is subnetted, 1 subnets C 2.2.2.2 is directly connected, Loopback2 3.0.0.0/32 is subnetted, 1 subnets O 3.3.3.3 [110/2] via 10.1.1.10, 00:06:50, FastEthernet1/1 10.0.0.0/30 is subnetted, 2 subnets C 10.1.1.8 is directly connected, FastEthernet1/1 C 10.1.1.4 is directly connected, FastEthernet1/0 R2#ping 1.1.1.1 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 1.1.1.1, timeout is 2 seconds: !!!!! Once more, we have connectivity, so with the passive-interface be very careful how you are going to use it and which protocol you are going to use it with. Now let's explore another feature, which is the default-information originate. This is used in conjunction with a static-default route to create an OSPF default static route. It is like advertising a static default route. To let all the routers know if you want to get to a destination network, this is the way to go. So, how would you configure something like that? Let's take a look. Use the following topology: R1(config)# ip route 0.0.0.0 0.0.0.0 GigabitEthernet2/0 R1(config)#router ospf 1 R1(config-router)#default-information originate Now that we have created a static route to an external network and we did the default-information originate command, what would the routing tables of the other routers look like? R2#sh ip route Codes: C - connected, S - static, R - RIP, M - mobile, B - BGP D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2 E1 - OSPF external type 1, E2 - OSPF external type 2 i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2 ia - IS-IS inter area, * - candidate default, U - per-user static route o - ODR, P - periodic downloaded static route Gateway of last resort is 10.1.1.5 to network 0.0.0.0 1.0.0.0/32 is subnetted, 1 subnets O 1.1.1.1 [110/2] via 10.1.1.5, 00:16:35, FastEthernet1/0 2.0.0.0/32 is subnetted, 1 subnets C 2.2.2.2 is directly connected, Loopback2 3.0.0.0/32 is subnetted, 1 subnets O 3.3.3.3 [110/2] via 10.1.1.10, 00:16:35, FastEthernet1/1 10.0.0.0/30 is subnetted, 2 subnets C 10.1.1.8 is directly connected, FastEthernet1/1 C 10.1.1.4 is directly connected, FastEthernet1/0 O 192.168.1.0/24 [110/2] via 10.1.1.5, 00:16:35, FastEthernet1/0 O*E2 0.0.0.0/0 [110/1] via 10.1.1.5, 00:16:35, FastEthernet1/0 R3#sh ip route Codes: C - connected, S - static, R - RIP, M - mobile, B - BGP D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2 E1 - OSPF external type 1, E2 - OSPF external type 2 i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2 ia - IS-IS inter area, * - candidate default, U - per-user static route o - ODR, P - periodic downloaded static route Gateway of last resort is 10.1.1.9 to network 0.0.0.0 1.0.0.0/32 is subnetted, 1 subnets O 1.1.1.1 [110/3] via 10.1.1.9, 00:17:17, FastEthernet0/0 2.0.0.0/32 is subnetted, 1 subnets O 2.2.2.2 [110/2] via 10.1.1.9, 00:17:17, FastEthernet0/0 3.0.0.0/32 is subnetted, 1 subnets C 3.3.3.3 is directly connected, Loopback3 10.0.0.0/30 is subnetted, 2 subnets C 10.1.1.8 is directly connected, FastEthernet0/0 O 10.1.1.4 [110/2] via 10.1.1.9, 00:17:17, FastEthernet0/0 O 192.168.1.0/24 [110/3] via 10.1.1.9, 00:17:17, FastEthernet0/0 O*E2 0.0.0.0/0 [110/1] via 10.1.1.9, 00:17:17, FastEthernet0/0 R4#sh ip route Codes: C - connected, S - static, R - RIP, M - mobile, B - BGP D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2 E1 - OSPF external type 1, E2 - OSPF external type 2 i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2 ia - IS-IS inter area, * - candidate default, U - per-user static route o - ODR, P - periodic downloaded static route Gateway of last resort is 192.168.1.1 to network 0.0.0.0 1.0.0.0/32 is subnetted, 1 subnets D EX 1.1.1.1 [170/5376] via 192.168.1.1, 00:12:38, GigabitEthernet2/0 2.0.0.0/32 is subnetted, 1 subnets D EX 2.2.2.2 [170/5376] via 192.168.1.1, 00:12:38, GigabitEthernet2/0 3.0.0.0/32 is subnetted, 1 subnets D EX 3.3.3.3 [170/5376] via 192.168.1.1, 00:12:38, GigabitEthernet2/0 10.0.0.0/30 is subnetted, 2 subnets D EX 10.1.1.8 [170/5376] via 192.168.1.1, 00:12:38, GigabitEthernet2/0 D EX 10.1.1.4 [170/5376] via 192.168.1.1, 00:12:38, GigabitEthernet2/0 C 192.168.1.0/24 is directly connected, GigabitEthernet2/0 D*EX 0.0.0.0/0 [170/5376] via 192.168.1.1, 00:12:38, GigabitEthernet2/0 So, this is how you can advertise a default route to external route, using OSPF. Obviously, you must configure EIGRP on R1 and R4 and do some redistribution. That is why all the routes are external, but you are advertising a way out using a static default route. To summarize, this article covered OSPF configurations,   features of OSPF, and different ways of advertising the networks. To know more about Multi-area OSPF configuration, check out the book CCNA Routing and Switching 200-125 Certification Guide. Brute forcing HTTP applications and web applications using Nmap [Tutorial] Discovering network hosts with ‘TCP SYN’ and ‘TCP ACK’ ping scans in Nmap[Tutorial] How to build a convolution neural network based malware detector using malware visualization [Tutorial]
Read more
  • 0
  • 0
  • 22899

article-image-how-to-build-a-relay-react-app-tutorial
Bhagyashree R
01 Jan 2019
12 min read
Save for later

How to build a Relay React App [Tutorial]

Bhagyashree R
01 Jan 2019
12 min read
Relay is used with both web and mobile React applications. It relies on a language called GraphQL which is used to fetch resources and to mutate those resources. The premise of Relay is that it can be scaled in ways that Redux and other approaches to handling state are limiting. It does this by eliminating them and keeping the focus on the data requirements of the component. In this article, we will build a Todo React Native application using Relay. By the end of this article, you should feel comfortable about how data moves around in a GraphQL centric architecture. At a high level, you can think of Relay as an implementation of Flux architecture patterns, and you can think of GraphQL as the interface that describes how the Flux stores within Relay work. At a more practical level, the value of Relay is ease of implementation. For example, with Redux, you have a lot of implementation work to do, just to populate the stores with data. This gets verbose over time. It's this verbosity that makes Redux difficult to scale beyond a certain point. [box type="shadow" align="" class="" width=""]This article is taken from the book React and React Native - Second Edition by Adam Boduch. This book guides you through building applications for web and native mobile platforms with React, JSX, Redux, and GraphQL.  To follow along with the examples implemented in this article, you can find the code in the GitHub repository of the book. [/box] TodoMVC and Relay TodoMVC example for Relay will be a robust yet concise example. We will walk through an example React Native implementation of a Todo app. The key is that it'll use the same GraphQL backend as the web UI. I've included the web version of the TodoMVC app in the code that ships with this book, but I won't dwell on the details of how it works. If you've worked on web development in the past 5 years, you've probably come across a sample Todo app. Here's what the web version looks like: Even if you haven't used any of the TodoMVC apps before, I would recommend playing with this one before trying to implement the native version, which is what you'll be doing for the remainder of the article. The goal of the native version that you're about to implement isn't functional parity. In fact, you're shooting for a very minimal subset of todo functionality. The aim is to show you that Relay works mostly the same on native platforms as it does on web platforms and that the GraphQL backend can be shared between web and native apps. The GraphQL schema The schema is the vocabulary used by GraphQL backend server and the Relay components in the frontend. The GraphQL type system enables the schema to describe the data that's available, and how to put it all together when a query request comes in. This is what makes the whole approach so scalable, the fact that the GraphQL runtime figures out how to put data together. All you need to supply are functions that tell GraphQL where the data is; for example, in a database or in some remote service endpoint. Let's take a look at the types used in the GraphQL schema for the TodoMVC app: You can find the code in this section on GitHub. import { GraphQLBoolean, GraphQLID, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLSchema, GraphQLString } from 'graphql'; import { connectionArgs, connectionDefinitions, connectionFromArray, cursorForObjectInConnection, fromGlobalId, globalIdField, mutationWithClientMutationId, nodeDefinitions, toGlobalId } from 'graphql-relay'; import { Todo, User, addTodo, changeTodoStatus, getTodo, getTodos, getUser, getViewer, markAllTodos, removeCompletedTodos, removeTodo, renameTodo } from './database'; const { nodeInterface, nodeField } = nodeDefinitions( globalId => { const { type, id } = fromGlobalId(globalId); if (type === 'Todo') { return getTodo(id); } if (type === 'User') { return getUser(id); } return null; }, obj => { if (obj instanceof Todo) { return GraphQLTodo; } if (obj instanceof User) { return GraphQLUser; } return null; } ); const GraphQLTodo = new GraphQLObjectType({ name: 'Todo', fields: { id: globalIdField(), complete: { type: GraphQLBoolean }, text: { type: GraphQLString } }, interfaces: [nodeInterface] }); const { connectionType: TodosConnection, edgeType: GraphQLTodoEdge } = connectionDefinitions({ nodeType: GraphQLTodo }); const GraphQLUser = new GraphQLObjectType({ name: 'User', fields: { id: globalIdField(), todos: { type: TodosConnection, args: { status: { type: GraphQLString, defaultValue: 'any' }, ...connectionArgs }, resolve: (obj, { status, ...args }) => connectionFromArray(getTodos(status), args) }, numTodos: { type: GraphQLInt, resolve: () => getTodos().length }, numCompletedTodos: { type: GraphQLInt, resolve: () => getTodos('completed').length } }, interfaces: [nodeInterface] }); const GraphQLRoot = new GraphQLObjectType({ name: 'Root', fields: { viewer: { type: GraphQLUser, resolve: getViewer }, node: nodeField } }); const GraphQLAddTodoMutation = mutationWithClientMutationId({ name: 'AddTodo', inputFields: { text: { type: new GraphQLNonNull(GraphQLString) } }, outputFields: { viewer: { type: GraphQLUser, resolve: getViewer }, todoEdge: { type: GraphQLTodoEdge, resolve: ({ todoId }) => { const todo = getTodo(todoId); return { cursor: cursorForObjectInConnection(getTodos(), todo), node: todo }; } } }, mutateAndGetPayload: ({ text }) => { const todoId = addTodo(text); return { todoId }; } }); const GraphQLChangeTodoStatusMutation = mutationWithClientMutationId({ name: 'ChangeTodoStatus', inputFields: { id: { type: new GraphQLNonNull(GraphQLID) }, complete: { type: new GraphQLNonNull(GraphQLBoolean) } }, outputFields: { viewer: { type: GraphQLUser, resolve: getViewer }, todo: { type: GraphQLTodo, resolve: ({ todoId }) => getTodo(todoId) } }, mutateAndGetPayload: ({ id, complete }) => { const { id: todoId } = fromGlobalId(id); changeTodoStatus(todoId, complete); return { todoId }; } }); const GraphQLMarkAllTodosMutation = mutationWithClientMutationId({ name: 'MarkAllTodos', inputFields: { complete: { type: new GraphQLNonNull(GraphQLBoolean) } }, outputFields: { viewer: { type: GraphQLUser, resolve: getViewer }, changedTodos: { type: new GraphQLList(GraphQLTodo), resolve: ({ changedTodoIds }) => changedTodoIds.map(getTodo) } }, mutateAndGetPayload: ({ complete }) => { const changedTodoIds = markAllTodos(complete); return { changedTodoIds }; } }); const GraphQLRemoveCompletedTodosMutation = mutationWithClientMutationId( { name: 'RemoveCompletedTodos', outputFields: { viewer: { type: GraphQLUser, resolve: getViewer }, deletedIds: { type: new GraphQLList(GraphQLString), resolve: ({ deletedIds }) => deletedIds } }, mutateAndGetPayload: () => { const deletedTodoIds = removeCompletedTodos(); const deletedIds = deletedTodoIds.map( toGlobalId.bind(null, 'Todo') ); return { deletedIds }; } } ); const GraphQLRemoveTodoMutation = mutationWithClientMutationId({ name: 'RemoveTodo', inputFields: { id: { type: new GraphQLNonNull(GraphQLID) } }, outputFields: { viewer: { type: GraphQLUser, resolve: getViewer }, deletedId: { type: GraphQLID, resolve: ({ id }) => id } }, mutateAndGetPayload: ({ id }) => { const { id: todoId } = fromGlobalId(id); removeTodo(todoId); return { id }; } }); const GraphQLRenameTodoMutation = mutationWithClientMutationId({ name: 'RenameTodo', inputFields: { id: { type: new GraphQLNonNull(GraphQLID) }, text: { type: new GraphQLNonNull(GraphQLString) } }, outputFields: { todo: { type: GraphQLTodo, resolve: ({ todoId }) => getTodo(todoId) } }, mutateAndGetPayload: ({ id, text }) => { const { id: todoId } = fromGlobalId(id); renameTodo(todoId, text); return { todoId }; } }); const GraphQLMutation = new GraphQLObjectType({ name: 'Mutation', fields: { addTodo: GraphQLAddTodoMutation, changeTodoStatus: GraphQLChangeTodoStatusMutation, markAllTodos: GraphQLMarkAllTodosMutation, removeCompletedTodos: GraphQLRemoveCompletedTodosMutation, removeTodo: GraphQLRemoveTodoMutation, renameTodo: GraphQLRenameTodoMutation } }); export default new GraphQLSchema({ query: GraphQLRoot, mutation: GraphQLMutation }); There are a lot of things being imported here, so I'll start with the imports. I wanted to include all of these imports because I think they're contextually relevant for this discussion. First, there's the primitive GraphQL types from the graphql library. Next, you have helpers from the graphql-relay library that simplify defining a GraphQL schema. Lastly, there's imports from your own database module. This isn't necessarily a database, in fact, in this case, it's just mock data. You could replace database with api for instance, if you needed to talk to remote API endpoints, or we could combine the two; it's all GraphQL as far as your React components are concerned. Then, you define some of your own GraphQL types. For example, the GraphQLTodo type has two fields—text and complete. One is a Boolean and one is a string. The important thing to note about GraphQL fields is the resolve() function. This is how you tell the GraphQL runtime how to populate these fields when they're required. These two fields simply return property values. Then, there's the GraphQLUser type. This field represents the user's entire universe within the UI, hence the name. The todos field, for example, is how you query for todo items from Relay components. It's resolved using the connectionFromArray() function, which is a shortcut that removes the need for more verbose field definitions. Then, there's the GraphQLRoot type. This has a single viewer field that's used as the root of all queries. Now let's take a closer look at the add todo mutation, as follows. I'm not going to go over every mutation that's used by the web version of this app, in the interests of space: const GraphQLAddTodoMutation = mutationWithClientMutationId({ name: 'AddTodo', inputFields: { text: { type: new GraphQLNonNull(GraphQLString) } }, outputFields: { viewer: { type: GraphQLUser, resolve: getViewer }, todoEdge: { type: GraphQLTodoEdge, resolve: ({ todoId }) => { const todo = getTodo(todoId); return { cursor: cursorForObjectInConnection(getTodos(), todo), node: todo }; } } }, mutateAndGetPayload: ({ text }) => { const todoId = addTodo(text); return { todoId }; } }); All mutations have a mutateAndGetPayload() method, which is how the mutation actually makes a call to some external service to change the data. The returned payload can be the changed entity, but it can also include data that's changed as a side-effect. This is where the outputFields come into play. This is the information that's handed back to Relay in the browser so that it has enough information to properly update components based on the side effects of the mutation. Don't worry, you'll see what this looks like from Relay's perspective shortly. The mutation type that you've created here is used to hold all application mutations. Lastly, here's how the entire schema is put together and exported from the module: export default new GraphQLSchema({ query: GraphQLRoot, mutation: GraphQLMutation }); Don't worry about how this schema is fed into the GraphQL server for now. Bootstrapping Relay At this point, you have the GraphQL backend up and running. Now, you can focus on your React components in the frontend. In particular, you're going to look at Relay in a React Native context, which really only has minor differences. For example, in web apps, it's usually react-router that bootstraps Relay. In React Native, it's a little different. Let's look at the App.js file that serves as the entry point for your native app: You can find the code in this section on GitHub. Let's break down what's happening here, starting with the environment constant: const environment = new Environment({ network: Network.create({ schema }), store: new Store(new RecordSource()) }); This is how you communicate with the GraphQL backend, by configuring a network. In this example, you're importing Network from relay-local-schema, which means that no network requests are being made. This is really handy for when you're getting started—especially building a React Native app. Next, there's the QueryRenderer component. This Relay component is used to render other components that depend on GraphQL queries. It expects a query property: query={graphql` query App_Query($status: String!) { viewer { ...TodoList_viewer } } `} Note that queries are prefixed by the module that they're in. In this case, App. This query uses a GraphQL fragment from another module, TodoList, and is named TodoList_viewer. You can pass variables to the query: variables={{ status: 'any' }} Then, the render property is a function that renders your components when the GraphQL data is ready: If something went wrong, error will contain information about the error. If there's no error and no props, it's safe to assume that the GraphQL data is still loading. Adding todo items In the TodoInput component, there's a text input that allows the user to enter new todo items. When they're done entering the todo, Relay will need to send a mutation to the backend GraphQL server. Here's what the component code looks like: You can find the code in this section on GitHub. It doesn't look that different from your typical React Native component. The piece that stands out is the mutation—AddTodoMutation. This is how you tell the GraphQL backend that you want a new todo node created. Let's see what the application looks like so far: The textbox for adding new todo items is just above the list of todo items. Now, let's look at the TodoList component, which is responsible for rendering the todo item list. Rendering todo items It's the job of the TodoList component to render the todo list items. When AddTodoMutation takes place, the TodoList component needs to be able to render this new item. Relay takes care of updating the internal data stores where all of our GraphQL data lives. Here's a look at the item list again, with several more todos added: Here's the TodoList component itself: You can find the code in this section on GitHub. The relevant GraphQL to get the data you need is passed as a second argument to createFragmentContainer(). This is the declarative data dependency for the component. When you render the <Todo> component, you're passing it the edge.todo data. Now, let's see what the Todo component itself looks like. Completing todo items The last piece of this application is rendering each todo item and providing the ability to change the status of the todo. Let's take a look at this code: You can find the code in this section on GitHub. The actual component that's rendered is a switch control and the item text. When the user marks the todo as complete, the item text is styled as crossed off. The user can also uncheck items. The ChangeTodoStatusMutation mutation sends the request to the GraphQL backend to change the todo state. The GraphQL backend then talks to any microservices that are needed to make this happen. Then, it responds with the fields that this component depends on. The important part of this code that I want to point out is the fragments used in the Relay container. This container doesn't actually use them directly. Instead, they're used by the todos query in the TodoList component (Todo.getFrament()). This is useful because it means that you can use the Todo component in another context, with another query, and its data dependencies will always be satisfied. In this article, we implemented some specific Relay and GraphQL ideas. Starting with the GraphQL schema, we learned how to declare the data that's used by the application and how these data types resolve to specific data sources, such as microservice endpoints. Then, we learned about bootstrapping GraphQL queries from Relay in your React Native app. Next, we walked through the specifics of adding, changing and listing todo items. The application itself uses the same schema as the web version of the Todo application, which makes things much easier when you're developing web and native React applications. If you found this post useful, do check out the book, React and React Native - Second Edition. This book guides you through building applications for web and native mobile platforms with React, JSX, Redux, and GraphQL. JavaScript mobile frameworks comparison: React Native vs Ionic vs NativeScript React introduces Hooks, a JavaScript function to allow using React without classes npm JavaScript predictions for 2019: React, GraphQL, and TypeScript are three technologies to learn
Read more
  • 0
  • 0
  • 58179
article-image-building-your-own-snapchat-like-ar-filter-on-android-using-tensorflow-lite-tutorial
Natasha Mathur
31 Dec 2018
13 min read
Save for later

Building your own Snapchat-like AR filter on Android using TensorFlow Lite [ Tutorial ]

Natasha Mathur
31 Dec 2018
13 min read
Augmented Reality (AR) filters that are used on applications such as Snapchat and Instagram have gained worldwide popularity. This tutorial is an excerpt taken from the book 'Machine Learning Projects for Mobile Applications' written by Karthikeyan NG. In this tutorial,  we will look at how you can build your own Augmented Reality (AR) filter using TensorFlow Lite, a platform that allows you to run machine learning models on mobile and embedded devices.  With this application, we will place AR filters on top of a real-time camera view. Using AR filters, we can add a mustache to a male's facial key point, and we can add a relevant emotional expression on top of the eyes. The TensorFlow Lite model is used to detect gender and emotion from the camera view. We will be looking at concepts such as MobileNet models and building the dataset required for model conversion before looking at how to build the Android application. MobileNet models We use the MobileNet model to identify gender, while the AffectNet model is used to detect emotion. Facial key point detection is achieved using Google's Mobile Vision API. TensorFlow offers various pre-trained models, such as drag and drop models, in order to identify approximately 1,000 default objects. When compared with other similar models such as the Inception model datasets, MobileNet works better with latency, size, and accuracy. In terms of output performance, there is a significant amount of lag, with a full-fledged model. However, the trade-off is acceptable when the model is deployable on a mobile device and for real-time offline model detection. The MobileNet architecture deals with a 3 x 3 convolution layer in a different way from a typical CNN. For a more detailed explanation of the MobileNet architecture, please visit https://arxiv.org/pdf/1704.04861.pdf. Let's look at an example of how to use MobileNet. Let's not build one more generic dataset in this case. Instead, we will write a simple classifier to find Pikachu in an image. The following are sample pictures showing an image of Pikachu and an image without Pikachu: Building the dataset To build our own classifier, we need to have datasets that contain images with and without Pikachu. You can start with 1,000 images on each database and you can pull down such images here: https://search.creativecommons.org/. Let's create two folders named pikachu and no-pikachu and drop those images accordingly. Always ensure that you have the appropriate licenses to use any images, especially for commercial purposes. Image scrapper from the Google and Bing API: https://github.com/rushilsrivastava/image_search. Now we have an image folder, which is structured as follows: /dataset/ /pikachu/[image1,..] /no-pikachu/[image1,..] Retraining of images  We can now start labeling our images. With TensorFlow, this job becomes easier. Assuming that you have installed TensorFlow already, download the following retraining script: curl https://github.com/tensorflow/hub/blob/master/examples/ image_retraining/retrain.py Let's retrain the image with the Python script now: python retrain.py \ --image_dir ~/MLmobileapps/Chapter5/dataset/ \ --learning_rate=0.0001 \ --testing_percentage=20 \ --validation_percentage=20 \ --train_batch_size=32 \ --validation_batch_size=-1 \ --eval_step_interval=100 \ --how_many_training_steps=1000 \ --flip_left_right=True \ --random_scale=30 \ --random_brightness=30 \ --architecture mobilenet_1.0_224 \ --output_graph=output_graph.pb \ --output_labels=output_labels.txt If you set validation_batch_size to -1, it will validate the whole dataset; learning_rate = 0.0001 works well. You can adjust and try this for yourself. In the architecture flag, we choose which version of MobileNet to use, from versions 1.0, 0.75, 0.50, and 0.25. The suffix number 224 represents the image resolution. You can specify 224, 192, 160, or 128 as well. Model conversion from GraphDef to TFLite TocoConverter is used to convert from a TensorFlow GraphDef file or SavedModel into either a TFLite FlatBuffer or graph visualization. TOCO stands for TensorFlow Lite Optimizing Converter. We need to pass the data through command-line arguments. There are a few command-line arguments listed in the following with TensorFlow 1.10.0: --output_file OUTPUT_FILE Filepath of the output tflite model. --graph_def_file GRAPH_DEF_FILE Filepath of input TensorFlow GraphDef. --saved_model_dir Filepath of directory containing the SavedModel. --keras_model_file Filepath of HDF5 file containing tf.Keras model. --output_format {TFLITE,GRAPHVIZ_DOT} Output file format. --inference_type {FLOAT,QUANTIZED_UINT8} Target data type in the output --inference_input_type {FLOAT,QUANTIZED_UINT8} Target data type of real-number input arrays. --input_arrays INPUT_ARRAYS Names of the input arrays, comma-separated. --input_shapes INPUT_SHAPES Shapes corresponding to --input_arrays, colon-separated. --output_arrays OUTPUT_ARRAYS Names of the output arrays, comma-separated. We can now use the toco tool to convert the TensorFlow model into a TensorFlow Lite model: toco \ --graph_def_file=/tmp/output_graph.pb --output_file=/tmp/optimized_graph.tflite --input_arrays=Mul --output_arrays=final_result --input_format=TENSORFLOW_GRAPHDEF --output_format=TFLITE --input_shape=1,${224},${224},3 --inference_type=FLOAT --input_data_type=FLOAT Similarly, we have two model files used in this application: the gender model and emotion model. These will be explained in the following two sections. To convert ML models in TensorFlow 1.9.0 to TensorFlow 1.11.0, use TocoConverter. TocoConverter is semantically identically to TFLite Converter. To convert models prior to TensorFlow 1.9, use the toco_convert function. Run help(tf.contrib.lite.toco_convert) to get details about acceptable parameters. Gender model This is built on the IMDB WIKI dataset, which contains 500k+ celebrity faces. It uses the MobileNet_V1_224_0.5 version of MobileNet. The link to the data model project can be found here: https://data.vision.ee.ethz.ch/cvl/rrothe/imdb-wiki/. It is very rare to find public datasets with thousands of images. This dataset is built on top of a large collection of celebrity faces. There are two common places: one is IMDb and the other one is Wikipedia. More than 100K celebrities' details were retrieved from their profiles from both sources through scripts. Then it was organized by removing noises(irrelevant content). Emotion model This is built on the AffectNet model with more than 1 million images. It uses the MobileNet_V2_224_1.4 version of MobileNet. The link to the data model project can be found here: http://mohammadmahoor.com/affectnet/. The AffectNet model is built by collecting and annotating facial images of more than 1 million faces from the internet. The images were sourced from three search engines, using around 1,250 related keywords in six different languages. Comparison of MobileNet versions In both of our models, we use different versions of MobileNet models. MobileNet V2 is mostly an updated version of V1 that makes it even more efficient and powerful in terms of performance. We will see a few factors between both the models: The picture above shows the numbers from MobileNet V1 and V2 belong to the model versions with 1.0 depth multiplier. It is better if the numbers are lower in this table. By seeing the results we can assume that V2 is almost twice as fast as V1 model. On a mobile device when memory access is limited than the computational capability V2 works very well. MACs—multiply-accumulate operations. This measures how many calculations are needed to perform inference on a single 224×224 RGB image. When the image size increases more MACs are required. From the number of MACs alone, V2 should be almost twice as fast as V1. However, it’s not just about the number of calculations. On mobile devices, memory access is much slower than computation. But here V2 has the advantage too: it only has 80% of the parameter count that V1 has. Now, let's look into the performance in terms of accuracy: The figure shown above is tested on ImageNet dataset. These numbers can be misleading as it depends on all the constraints that is taken into account while deriving these numbers. The IEEE paper behind the model can be found here: http://mohammadmahoor.com/wp-content/uploads/2017/08/AffectNet_oneColumn-2.pdf. Building the Android application Now create a new Android project from Android Studio. This should be called ARFilter, or whatever name you prefer: On the next screen, select the Android OS versions that our application supports and select API 15 which is not shown on the image. That covers almost all existing Android phones. When you are ready, press Next. On the next screen, select Add No Activity and click Finish. This creates an empty project: Once the project is created, let's add one Empty Activity. We can select different activity styles based on our needs: Name the created activity Launcher Activity by selecting the checkbox. This adds an intent filter under the particular activity in the AndroidManifest.xml file: <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter>: To advertise which implicit intents your app can receive, declare one or more intent filters for each of your app components with an <intent-filter> element in your manifest file. Each intent filter specifies the type of intents it accepts based on the intent's action, data, and category. The system delivers an implicit intent to your app component only if the intent can pass through one of your intent filters. Here, the intent is to keep this activity as the first activity when the app is opened by the user. Next, we will name the launcher activity: Once the activity is created, let's start designing the user interface (UI) layout for the activity. Here, the user selects which model to utilize in this application. We have two models for gender and emotion detection, whose details we discussed earlier. In this activity, we will add two buttons and their corresponding model classifiers, shown as follows: With the selection of the corresponding model, we will launch the next activity accordingly using a clickListener event with the ModelSelectionActivity class as follows. Based on the clicks on the buttons on gender identification or emotion identification, we will pass on the information to the ARFilterActivity. So that the corresponding model will be loaded into memory: @Override public void onClick(View view) { int id = view.getId(); if(id==R.id.genderbtn){ Intent intent = new Intent(this, ARFilterActivity.class); intent.putExtra(ARFilterActivity.MODEL_TYPE,"gender"); startActivity(intent); } else if(id==R.id.emotionbtn){ Intent intent = new Intent(this,ARFilterActivity.class); intent.putExtra(ARFilterActivity.MODEL_TYPE,"emotion"); startActivity(intent); } } Intent: An Intent is a messaging object you can use to request an action from another app component. Although intents facilitate communication between components in several ways, there are three fundamental use cases such as starting an Activity, starting a service and delivering a broadcast. In ARFilterActivity, we will have the real-time view classification. The object that has been passed on will be received inside the filter activity, where the corresponding classifier will be invoked as follows. Based on the classifier selected from the previous activity, the corresponding model will be loaded into ARFilterActivity inside the OnCreate() method as shown as follows: public static String classifierType(){ String type = mn.getIntent().getExtras().getString("TYPE"); if(type!=null) { if(type.equals("gender")) return "gender"; else return "emotion"; } else return null; } The UI will be designed accordingly in order to display the results in the bottom part of the layout via the activity_arfilter layout as follows. CameraSourcePreview initiates the Camera2 API for a view inside that we will add GraphicOverlay class. It is a view which renders a series of custom graphics to be overlayed on top of an associated preview (that is the camera preview). The creator can add graphics objects, update the objects, and remove them, triggering the appropriate drawing and invalidation within the view. It supports scaling and mirroring of the graphics relative the camera's preview properties. The idea is that detection item is expressed in terms of a preview size but need to be scaled up to the full view size, and also mirrored in the case of the front-facing camera: <com.mlmobileapps.arfilter.CameraSourcePreview android:id="@+id/preview" android:layout_width="wrap_content" android:layout_height="wrap_content"> <com.mlmobileapps.arfilter.GraphicOverlay android:id="@+id/faceOverlay" android:layout_width="match_parent" android:layout_height="match_parent" /> </com.mlmobileapps.arfilter.CameraSourcePreview> We use the CameraPreview class from the Google open source project and the CAMERA object needs user permission based on different Android API levels: Link to Google camera API: https://github.com/googlesamples/android-Camera2Basic. Once we have the Camera API ready, we need to have the appropriate permission from the user side to utilize the camera as shown below. We need these following permissions: Manifest.permission.CAMERA Manifest.permission.WRITE_EXTERNAL_STORAGE private void requestPermissionThenOpenCamera() { if(ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { Log.e(TAG, "requestPermissionThenOpenCamera: "+Build.VERSION.SDK_INT); useCamera2 = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP); createCameraSourceFront(); } else { ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE_PERMISSION); } } else { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION); } } With this, we now have an application that has a screen where we can choose which model to load. On the next screen, we have the camera view ready. We now have to load the appropriate model, detect the face on the screen, and apply the filter accordingly. Face detection on the real camera view is done through the Google Vision API. This can be added on your build.gradle as a dependency as follows. You should always use the latest version of the api: api 'com.google.android.gms:play-services-vision:15.0.0' The image classification object is initialized inside the OnCreate() method of the ARFilterActivity and inside the ImageClassifier class. The corresponding model is loaded based on user selection as follows: private void initPaths(){ String type = ARFilterActivity.classifierType(); if(type!=null) { if(type.equals("gender")){ MODEL_PATH = "gender.lite"; LABEL_PATH = "genderlabels.txt"; } else{ MODEL_PATH = "emotion.lite"; LABEL_PATH = "emotionlabels.txt"; } } } Once the model is decided, we will read the file and load them into memory. Thus in this article, we looked at concepts such as mobile net models and building the dataset required for the model application, we then looked at how to build a Snapchat-like AR filter.  If you want to know the further steps to build AR filter such as loading the model, and so on, be sure to check out the book  'Machine Learning Projects for Mobile Applications'. Snapchat source code leaked and posted to GitHub Snapchat is losing users – but revenue is up 15 year old uncovers Snapchat’s secret visual search function
Read more
  • 0
  • 0
  • 24006

article-image-how-to-perform-event-handling-in-react-tutorial
Bhagyashree R
31 Dec 2018
11 min read
Save for later

How to perform event handling in React [Tutorial]

Bhagyashree R
31 Dec 2018
11 min read
React has a unique approach to handling events: declaring event handlers in JSX. The differentiating factor with event handling in React components is that it's declarative. Contrast this with something like jQuery, where you have to write imperative code that selects the relevant DOM elements and attaches event handler functions to them. The advantage with the declarative approach to event handlers in JSX markup is that they're part of the UI structure. Not having to track down the code that assigns event handlers is mentally liberating. [box type="shadow" align="" class="" width=""]This article is taken from the book React and React Native - Second Edition by Adam Boduch. This book guides you through building applications for web and native mobile platforms with React, JSX, Redux, and GraphQL. To follow along with the examples implemented in this article, you can find the code in the GitHub repository of the book.[/box] In this tutorial, we will look at how event handlers for particular elements are declared in JSX. It will walk you through the implementation of inline and higher-order event handler functions. Then you'll learn how React actually maps event handlers to DOM elements under the hood. Finally, you'll learn about the synthetic events that React passes to event handler functions, and how they're pooled for performance purposes. Declaring event handlers In this section, you'll write a basic event handler, so that you can get a feel for the declarative event handling syntax found in React applications. Then, we will see how to use generic event handler functions. Declaring handler functions Let's take a look at a basic component that declares an event handler for the click event of an element: Find the code for this section in GitHub. The event handler function, this.onClick(), is passed to the onClick property of the <button> element. By looking at this markup, it's clear what code is going to run when the button is clicked. Multiple event handlers What I really like about the declarative event handler syntax is that it's easy to read when there's more than one handler assigned to an element. Sometimes, for example, there are two or three handlers for an element. Imperative code is difficult to work with for a single event handler, let alone several of them. When an element needs more handlers, it's just another JSX attribute. This scales well from a code maintainability perspective: Find the code for this section in GitHub. This input element could have several more event handlers, and the code would be just as readable. As you keep adding more event handlers to your components, you'll notice that a lot of them do the same thing. Next, you'll learn how to share generic handler functions across components. Importing generic handlers Any React application is likely going to share the same event handling logic for different components. For example, in response to a button click, the component should sort a list of items. It's these types of generic behaviors that belong in their own modules so that several components can share them. Let's implement a component that uses a generic event handler function: Find the code for this section on GitHub. Let's walk through what's going on here, starting with the imports. You're importing a function called reverse(). This is the generic event handler function that you're using with your <button> element. When it's clicked, the list should reverse its order. The onReverseClick method actually calls the generic reverse() function. It is created using bind() to bind the context of the generic function to this component instance. Finally, looking at the JSX markup, you can see that the onReverseClick() function is used as the handler for the button click. So how does this work, exactly? Do you have a generic function that somehow changes the state of this component because you bound context to it? Well, pretty much, yes, that's it. Let's look at the generic function implementation now: Find the code for this section on GitHub. This function depends on a this.state property and an items array within the state. The key is that the state is generic; an application could have many components with an items array in its state. Here's what our rendered list looks like: As expected, clicking the button causes the list to sort, using your generic reverse() event handler: Next, you'll learn how to bind the context and the argument values of event handler functions. Event handler context and parameters In this section, you'll learn about React components that bind their event handler contexts and how you can pass data into event handlers. Having the right context is important for React event handler functions because they usually need access to component properties or state. Being able to parameterize event handlers is also important because they don't pull data out of DOM elements. Getting component data In this section, you'll learn about scenarios where the handler needs access to component properties, as well as argument values. You'll render a custom list component that has a click event handler for each item in the list. The component is passed an array of values as follows: Find the code for this section on GitHub. Each item in the list has an id property, used to identify the item. You'll need to be able to access this ID when the item is clicked in the UI so that the event handler can work with the item. Here's what the MyList component implementation looks like: Find the code for this section on GitHub. Here is what the rendered list looks like: You have to bind the event handler context, which is done in the constructor. If you look at the onClick() event handler, you can see that it needs access to the component so that it can look up the clicked item in this.props.items. Also, the onClick() handler is expecting an id parameter. If you take a look at the JSX content of this component, you can see that calling bind() supplies the argument value for each item in the list. This means that when the handler is called in response to a click event, the id of the item is already provided. Higher-order event handlers A higher-order function is a function that returns a new function. Sometimes, higher-order functions take functions as arguments too. In the preceding example, you used bind() to bind the context and argument values of your event handler functions. Higher-order functions that return event handler functions are another technique. The main advantage of this technique is that you don't call bind() several times. Instead, you just call the function where you want to bind parameters to the function. Let's look at an example component: Find the code for this section on GitHub. This component renders three buttons and has three pieces of state—a counter for each button. The onClick() function is automatically bound to the component context because it's defined as an arrow function. It takes a name argument and returns a new function. The function that is returned uses this name value when called. It uses computed property syntax (variables inside []) to increment the state value for the given name. Here's what that component content looks like after each button has been clicked a few times: Inline event handlers The typical approach to assigning handler functions to JSX properties is to use a named function. However, sometimes you might want to use an inline function. This is done by assigning an arrow function directly to the event property in the JSX markup: Find the code for this section on GitHub. The main use of inlining event handlers like this is when you have a static parameter value that you want to pass to another function. In this example, you're calling console.log() with the string clicked. You could have set up a special function for this purpose outside of the JSX markup by creating a new function using bind(), or by using a higher-order function. But then you would have to think of yet another name for yet another function. Inlining is just easier sometimes. Binding handlers to elements When you assign an event handler function to an element in JSX, React doesn't actually attach an event listener to the underlying DOM element. Instead, it adds the function to an internal mapping of functions. There's a single event listener on the document for the page. As events bubble up through the DOM tree to the document, the React handler checks to see whether any components have matching handlers. The process is illustrated here: Why does React go to all of this trouble, you might ask? To keep the declarative UI structures separated from the DOM as much as possible. For example, when a new component is rendered, its event handler functions are simply added to the internal mapping maintained by React. When an event is triggered and it hits the document object, React maps the event to the handlers. If a match is found, it calls the handler. Finally, when the React component is removed, the handler is simply removed from the list of handlers. None of these DOM operations actually touch the DOM. It's all abstracted by a single event listener. This is good for performance and the overall architecture (keep the render target separate from the application code). Synthetic event objects When you attach an event handler function to a DOM element using the native addEventListener() function, the callback will get an event argument passed to it. Event handler functions in React are also passed an event argument, but it's not the standard Event instance. It's called SyntheticEvent, and it's a simple wrapper for native event instances. Synthetic events serve two purposes in React: Provides a consistent event interface, normalizing browser inconsistencies Synthetic events contain information that's necessary for propagation to work Here's an illustration of the synthetic event in the context of a React component: Event pooling One challenge with wrapping native event instances is that this can cause performance issues. Every synthetic event wrapper that's created will also need to be garbage collected at some point, which can be expensive in terms of CPU time. For example, if your application only handles a few events, this wouldn't matter much. But even by modest standards, applications respond to many events, even if the handlers don't actually do anything with them. This is problematic if React constantly has to allocate new synthetic event instances. React deals with this problem by allocating a synthetic instance pool. Whenever an event is triggered, it takes an instance from the pool and populates its properties. When the event handler has finished running, the synthetic event instance is released back into the pool, as shown here: This prevents the garbage collector from running frequently when a lot of events are triggered. The pool keeps a reference to the synthetic event instances, so they're never eligible for garbage collection. React never has to allocate new instances either. However, there is one gotcha that you need to be aware of. It involves accessing the synthetic event instances from asynchronous code in your event handlers. This is an issue because, as soon as the handler has finished running, the instance goes back into the pool. When it goes back into the pool, all of its properties are cleared. Here's an example that shows how this can go wrong: Find the code for this section on GitHub. The second call to  console.log() is attempting to access a synthetic event property from an asynchronous callback that doesn't run until the event handler completes, which causes the event to empty its properties. This results in a warning and an undefined value. This tutorial introduced you to event handling in React. The key differentiator between React and other approaches to event handling is that handlers are declared in JSX markup. This makes tracking down which elements handle which events much simpler. We learned that it's a good idea to share event handling functions that handle generic behavior.  We saw the various ways to bind the event handler function context and parameter values. Then, we discussed the inline event handler functions and their potential use, as well as how React actually binds a single DOM event handler to the document object. Synthetic events are an abstraction that wraps the native event, and you learned why they're necessary and how they're pooled for efficient memory consumption. If you found this post useful, do check out the book, React and React Native - Second Edition. This book guides you through building applications for web and native mobile platforms with React, JSX, Redux, and GraphQL. JavaScript mobile frameworks comparison: React Native vs Ionic vs NativeScript React introduces Hooks, a JavaScript function to allow using React without classes React 16.6.0 releases with a new way of code splitting, and more!
Read more
  • 0
  • 0
  • 49914

article-image-why-moving-from-a-monolithic-architecture-to-microservices-is-so-hard-gitlabs-jason-plum-breaks-it-down-kubeconcnc-talk
Amrata Joshi
19 Dec 2018
12 min read
Save for later

Why moving from a monolithic architecture to microservices is so hard, Gitlab’s Jason Plum breaks it down [KubeCon+CNC Talk]

Amrata Joshi
19 Dec 2018
12 min read
Last week, at the KubeCon+CloudNativeCon North America 2018, Jason Plum, Sr. software engineer, distribution at GitLab spoke about GitLab, Omnibus, and the concept of monolith and its downsides. He spent the last year working on the cloud native helm charts and breaking out a complicated pile of code. This article highlights few insights from Jason Plum’s talk on Monolith to Microservice: Pitchforks Not Included at the KubeCon + CloudNativeCon. Key takeaways “You could not have seen the future that you live in today, learn from what you've got in the past, learn what's available now and work your way to it.” - Jason Plum GitLab’s beginnings as the monolithic project provided the means for focused acceleration and innovation. The need to scale better and faster than the traditional models caused to reflect on our choices, as we needed to grow beyond the current architecture to keep up. New ways of doing things require new ways of looking at them. Be open minded, and remember your correct choices in the past could not see the future you live in. “So the real question people don't realize is what is GitLab?”- Jason Plum Gitlab is the first single application to have the entire DevOps lifecycle in a single Interface. Omnibus - The journey from a package to a monolith “We had a group of people working on a single product to binding that and then we took that, we bundled that. And we shipped it and we shipped it and we shipped it and we shipped it and all the twenties every month for the entire lifespan of this company we have done that, that's not been easy. Being a monolith made that something that was simple to do at scale.”- Jason Plum In the beginning it was simple as Ruby on Rails was on a single codebase and users had to deploy it from source. Just one gigantic code was used but that's not the case these days. Ruby on Rails is still used for the primary application but now a shim proxy called workhorse is used that takes the heavy lifting away from Ruby. It ensures the users and their API’s are are responsive. The team at GitLab started packaging this because doing everything from source was difficult. They created the Omnibus package which eventually became the gigantic monolith. Monoliths make sense because... Adding features is simple It’s easy as everything is one bundle Clear focus for Minimum Viable Product (MVP) Advantages of Omnibus Full-stack bundle provides all components necessary to use every feature of GitLab. Simple to install. Components can be individually enabled/disabled. East to distribute. Highly controlled, version locked components. Guaranteed configuration stability. The downsides of monoliths “The problem is this thing is massive” - Jason Plum The Omnibus package can work on any platform, any cloud and under any distribution. But the question is how many of us would want to manage fleets of VMs? This package has grown so much that it is 1.5 gigabytes and unpacked. It has all the features and is still usable. If a user downloads 500 megabytes as an installation package then it unpacks almost a gigabyte and a half. This package contains everything that is required to run the SaaS but the problem is that this package is massive. “The trick is Git itself is the reason that moving to cloud native was hard.” - Jason Plum While using Git, the users run a couple of commands, they push them and deploy the app. But at the core of that command is how everything is handled and how everything is put together. Git works with snapshots of the entire file. The number of files include, every file the user has and every version the user had. It also involves all the indexes and references and some optimizations. But the problem is the more the files, the harder it gets. “Has anybody ever checked out the Linux tree? You check out that tree, get your coffee, come back check out, any branch I don't care what it is and then dip that against current master. How many files just got read on the file system?” - Jason Plum When you come back you realize that all the files that are marked as different and between the two of them when you do diff, that information is not stored, it's not greeting and it is not even cutting it out. It is running differently on all of those files. Imagine how bad that gets when you have 10 million lines of code in a repository that's 15 years old ?  That’s expensive in terms of performance.  - Jason Plum Traditional methods - A big problem “Now let's actually go and make a branch make some changes and commit them right. Now you push them up to your fork and now you go into add if you on an M R. Now it's my job to do the thing that was already hard on your laptop, right? Okay cool, that's one of you, how about 10,000 people a second right do you see where this is going? Suddenly it's harder but why is this the problem?” - Jason Plum The answer is traditional methods, as they are quite slow. If we have hundreds of things in the fleet, accessing tens of machines that are massive and it still won’t work because the traditional methods are a problem. Is NFS a solution to this problem? NFS (Network File System) works well when there are just 10 or 100 people. But if a user is asked to manage an NFS server for 5,000 people, one might rather choose pitchfork. NFS is capable but it can’t work at such a scale. The Git team now has a mount that has to be on every single node, as the API code and web code and other processes which needs to be functional enough to read the files. The team has previously used Garrett, Lib Git to read the files on the file system. Every time, one reads the file, the whole file used to get pulled. This gave rise to another problem, disk i/o problems. Since, everybody tries to read the disparate set of files, the traffic increases. “Okay so we have definitely found a scaling limit now we can only push the traditional methods of up and out so far before we realize that that's just not going to work because we don't have big enough pipes, end of line. So now we've got all of this and we've just got more of them and more of them and more of them. And all of a sudden we need to add 15 nodes to the fleet and another 15 nodes to the fleet and another 15 nodes to the fleet to keep up with sudden user demand. With every single time we have to double something the choke points do not grow - they get tighter and tighter” - Jason Plum The team decided to take a second look at the problem and started working on a project called Gitaly. They took the API calls that the users would make to live Git. So the Git mechanics was sent over a GRPC and then Gitaly was put on the actual file servers. Further the users were asked to call for a diff on whatever they want and then Gitaly was asked for the response. There is no need of NFS now. “I can send a 1k packet get a 4k response instead of NFS and reading 10,000 files. We centralized everything across and this gives us the ability to actually meet throughput because that pipe that's not getting any bigger suddenly has 1/10 of the traffic going through it.” - Jason Plum This leaves more space for users to easily get to the file servers and further removes the need of NFS mounts for everything. Incase one node is lost then half of the fleet is not lost in an instant. How is Gitaly useful? With Gitaly the throughput requirement significantly reduced. The service nodes no more need disk access. It provides optimization for specific problems. How to solve Git’s performance related issue? For better optimization and performance it is important to treat it like a service or like a database. The file system is still in use and all of the accesses to the files are on the node where we have the best performance and best caching and there is no issue with regards to the network. “To take the monolith and rip a chunk out make it something else and literally prop the thing up, but how long are we going to be able to do this?” - Jason Plum If a user plans to upload something then he/she has to use a file system and which means that NFS hasn't gone away. Do we really need to have NFS because somebody uploaded a cat picture? Come on guys we can do better than that right?- Jason Plum The next solution was to take everything as a traditional file that does not get and move into object store as an option. This matters because there is no need to have a file system locally. The files can be handed over to a service that works well. And it could run on Prem in a cloud and can be handled by any number of men and service providers. Pets cattle is a popular term by CERN which means anything that can be replaced easily is cattle and anything that you have to care and feed for on a regular basis is a pet. The pet could be the stateful information, for example, database. The problem can be better explained with configuring the Omnibus at scale. If there are  hundreds of the VM’s and they are getting installed, further which the entire package is getting installed. So now there are 20 gigabytes per VM. The package needs to be downloaded for all the VM’s which means almost 500 megabytes. All the individual components can be configured out of the Omnibus. But even the load gets spreaded, it will still remain this big. And each of the nodes will at least take two minutes to come up from. So to speed up this process, the massive stack needs to be broken down into chunks and containers so they can be treated as individualized services. Also, there is no need of NFS as the components are no longer bound to the NFS disk. And this process would now take just five seconds instead of two minutes. A problem called legacy debt, a shared file system expectation which was a bugger. If there are separate containers and there is no shared disk then it could again give rise to a problem. “I can't do a shared disk because if we do shared disk through rewrite many. What's the major provider that will do that for us on every platform, anybody remember another three-letter problem.” - Jason Plum Then there came an interesting problem called workhorse, a smart proxy that talks to the UNIX sockets and not TCP. Though this problem got fixed. Time constraints - another problem “We can't break existing users and we can't have hiccups we have to think about everything ahead of time plan well and execute.” - Jason Plum Time constraints is a serious problem for a project’s developers, the development resources milestones, roadmaps deliverables. The new features would keep on coming into the project. The project would keep on functioning in the background but the existing users can’t be kept waiting. Is it possible to define individual component requirements? “Do you know how much CPU you need when idle versus when there's 10 people versus literally some guy clicking around and if files because he's one to look at what the kernel would like in 2 6 2 ?”- Jason Plum Monitoring helps to understand the component requirements. Metrics and performance data are few of the key elements for getting the exact component requirements. Other parameters like network, throughput, load balance, services etc also play an important role. But the problem is how to deal with throughput? How to balance the services? How to ensure that those services are always up? Then the other question comes up regarding the providers and load balancers as everyone doesn’t want to use the same load balancers or the same services. The system must support all the load balancers from all the major cloud providers and which is difficult. Issues with scaling “Maybe 50 percent for the thing that needs a lot of memory is a bad idea. I thought 50 percent was okay because when I ran a QA test against it, it didn't ever use more than 50 percent of one CPU. Apparently when I ran three more it now used 115 percent and I had 16 pounds and it fell over again.” - Jason Plum It's important to know what things needs to be scaled horizontally and which ones needs to be scaled vertically. To go automated or manual is also a crucial question. Also, it is equally important to understand which things should be configurable and how to tweak them as the use cases may vary from project to project. So, one should know how to go about a test and how to document a test. Issues with resilience “What happens to the application when a node, a whole node disappears off the cluster? Do you know how that behaves?” - Jason Plum It is important to understand which things shouldn't be on the same nodes. But the problem is how to recover it. These things are not known and by the time one understands the problem and the solution, it is too late. We need new ways of examining these issues and for planning the solution. Jason’s insightful talk on Monolith to Microservice gives a perfect end to the KubeCon + CloudNativeCon and is a must watch for everyone. Kelsey Hightower on Serverless and Security on Kubernetes at KubeCon + CloudNative RedHat contributes etcd, a distributed key-value store project, to the Cloud Native Computing Foundation at KubeCon + CloudNativeCon Oracle introduces Oracle Cloud Native Framework at KubeCon+CloudNativeCon 2018
Read more
  • 0
  • 0
  • 19893
article-image-8-programming-languages-to-learn-in-2019
Richard Gall
19 Dec 2018
9 min read
Save for later

8 programming languages to learn in 2019

Richard Gall
19 Dec 2018
9 min read
Learning new skills takes time - that's why, before learning something, you need to know that what you're learning is going to be worthwhile. This is particularly true when deciding which programming language to learn. As we approach the new year, it's a good time to reflect on our top learning priorities for 2019. But which programming should you learn in 2019? We’ve put together a list of the top programming languages to learn in the new year - as well as reasons you should learn them, and some suggestions for how you can get started. This will help you take steps to expand your skill set in 2019 in the way that’s right for you. Want to learn a new programming language? We have thousands of eBooks and videos in our $5 sale to help you get to grips with everything from Python to Rust. Python Python has been a growing programming language for some time and it shows no signs of disappearing. There are a number of reasons for this, but the biggest is the irresistible allure of artificial intelligence. Once you know Python, performing some relatively sophisticated deep learning tasks becomes relatively easy, not least because of the impressive ecosystem of tools that surround it, like TensorFlow. But Python’s importance isn’t just about machine learning. It’s flexibility means it has a diverse range of applications. If you’re a full-stack developer, for example, you might find Python useful for developing backend services and APIs; equally, if you’re in security or SRE, Python can be useful for automating aspects of your infrastructure to keep things secure and reliable. Put simply, Python is a useful addition to your skill set. Learn Python in 2019 if... You’re new to software development You want to try your hand at machine learning You want to write automation scripts Want to get started? Check out these titles: Clean Code in Python Learning Python Learn Programming in Python with Cody Jackson Python for Everyday Life [Video]       Go Go isn’t quite as popular as Python, but it is growing rapidly. And its fans are incredibly vocal about why they love it: it’s incredibly simple, yet also amazingly powerful. The reason for this is its creation: it was initially developed by Google that wanted a programming language that could handle the complexity of the systems they were developing, without adding to complexity in terms of knowledge and workflows. Combining the best aspects of functional and object oriented programming, as well as featuring a valuable set of in-built development tools, the language is likely to only go from strength to strength over the next 12 months. Learn Go in 2019 if… You’re a backend or full-stack developer looking to increase your language knowledge You’re working in ops or SRE Looking for an alternative to Python Learn Go with these eBooks and videos: Mastering Go Cloud Native programming with Golang Hands-On Go Programming Hands-On Full-Stack Development with Go       Rust In Stack Overflow’s 2018 developer survey Rust was revealed to be the best loved language among the developers using it. 80% of respondents said they loved using it or wanted to use it. Now, while Rust lacks the simplicity of Go and Python, it does do what it sets out to do very well - systems programming that’s fast, efficient, and secure. In fact, developers like to debate the merits of Rust and Go - it seems they occupy the minds of very similar developers. However, while they do have some similarities, there are key differences that should make it easier to decide which one you learn. At a basic level, Rust is better for lower level programming, while Go will allow you to get things done quickly. Rust does have a lot of rules, all of which will help you develop incredibly performant applications, but this does mean it has a steeper learning curve than something like Go. Ultimately it will depend on what you want to use the language for and how much time you have to learn something new. Learn Rust in 2019 if… You want to know why Rust developers love it so much You do systems programming You have a bit of time to tackle its learning curve Learn Rust with these titles: Rust Quick Start Guide Building Reusable Code with Rust [Video] Learning Rust [Video] Hands-On Concurrency with Rust       TypeScript TypeScript has quietly been gaining popularity over recent years. But it feels like 2018 has been the year that it has really broke through to capture the imagination of the wider developer community. Perhaps it’s just Satya Nadella’s magic... More likely, however, it’s because we’re now trying to do too much with plain old JavaScript. We simply can’t build applications of the complexity we want without drowning in lines of code. Essentially, TypeScript bulks up JavaScript, and makes it suitable for building applications of the future. It’s no surprise that TypeScript is now fundamental to core JavaScript frameworks - even Google decided to use it in Angular. But it’s not just for front end JavaScript developers - there are examples of Java and C# developers looking closely at TypeScript, as it shares many features with established statically typed languages. Learn TypeScript in 2019 if… You’re a JavaScript developer You’re a Java or C# developer looking to expand their horizons Learn TypeScript in 2019: TypeScript 3.0 Quick Start Guide TypeScript High Performance Introduction to TypeScript [Video]         Scala Scala has been around for some time, but its performance gains over Java have seen it growing in popularity in recent years. It isn’t the easiest language to learn - in comparison with other Java-related languages, like Kotlin, which haven’t strayed far from its originator, Scala is almost an attempt to rewrite the rule book. It’s a good multi-purpose programming language that brings together functional programming principles and the object oriented principles you find in Java. It’s also designed for concurrency, giving you a scale of power that just isn’t possible. The one drawback of Scala is that it doesn’t have the consistency in its ecosystem in the way that, say, Java does. This does mean, however, that Scala expertise can be really valuable if you have the time to dedicate time to really getting to know the language. Learn Scala in 2019 if… You’re looking for an alternative to Java that’s more scalable and handles concurrency much better You're working with big data Learn Scala: Learn Scala Programming Professional Scala [Video] Scala Machine Learning Projects Scala Design Patterns - Second Edition       Swift Swift started life as a replacement for Objective-C for iOS developers. While it’s still primarily used by those in the Apple development community, there are some signs that Swift could expand beyond its beginnings to become a language of choice for server and systems programming. The core development team have consistently demonstrated they have a sense of purpose is building a language fit for the future, with versions 3 and 4 both showing significant signs of evolution. Fast, relatively easy to learn, and secure, not only has Swift managed to deliver on its brief to offer a better alternative to Objective-C, it also looks well-suited to many of the challenges programmers will be facing in the years to come. Learn Swift in 2019 if… You want to build apps for Apple products You’re interested in a new way to write server code Learn Swift: Learn Swift by Building Applications Hands-On Full-Stack Development with Swift Hands-On Server-Side Web Development with Swift         Kotlin It makes sense for Kotlin to follow Swift. The parallels between the two are notable; it might be crude, but you could say that Kotlin is to Java what Swift is to Objective-C. There are, of course, some who feel that the comparison isn’t favorable, with accusations that one language is merely copying the other, but perhaps the similarities shouldn’t really be that surprising - they’re both trying to do the same things: provide a better alternative to what already exists. Regardless of the debates, Kotlin is a particularly compelling language if you’re a Java developer. It works extremely well, for example, with Spring Boot to develop web services. Certainly as monolithic Java applications shift into microservices, Kotlin is only going to become more popular. Learn Kotlin in 2019 if… You’re a Java developer that wants to build better apps, faster You want to see what all the fuss is about from the Android community Learn Kotlin: Kotlin Quick Start Guide Learning Kotlin by building Android Applications Learn Kotlin Programming [Video]         C Most of the languages on this list are pretty new, but I’m going to finish with a classic that refuses to go away. C has a reputation for being complicated and hard to learn, but it remains relevant because you can find it in so much of the software we take for granted. It’s the backbone of our operating systems, and used in everyday objects that have software embedded in them. Together, this means C is a language worth learning because it gives you an insight into how software actually works on machines. In a world where abstraction and accessibility rules the software landscape, getting beneath everything can be extremely valuable. Learn C in 2019 if… You’re looking for a new challenge You want to gain a deeper understanding of how software works on your machine You’re interested in developing embedded systems and virtual reality projects Learn C: Learn and Master C Programming For Absolute Beginners! [Video]
Read more
  • 0
  • 0
  • 48669

article-image-4-things-in-tech-that-might-die-in-2019
Richard Gall
19 Dec 2018
10 min read
Save for later

4 things in tech that might die in 2019

Richard Gall
19 Dec 2018
10 min read
If you’re in and around the tech industry, you’ve probably noticed that hype is an everyday reality. People spend a lot of time talking about what trends and technologies are up and coming and what people need to be aware of - they just love it. Perhaps second only to the fashion industry, the tech world moves through ideas quickly, with innovation piling up upon the next innovation. For the most part, our focus is optimistic: what is important? What’s actually going to shape the future? But with so much change there are plenty of things that disappear completely or simply shift out of view. Some of these things may have barely made an impression, others may have been important but are beginning to be replaced with other, more powerful, transformative and relevant tools. So, in the spirit of pessimism, here is a list of some of the trends and tools that might disappear from view in 2019. Some of these have already begun to sink, while others might leave you pondering whether I’ve completely lost my marbles. Of course, I am willing to be proven wrong. While I will not be eating my hat or any other item of clothing, I will nevertheless accept defeat with good grace in 12 months time. Blockchain Let’s begin with a surprise. You probably expected Blockchain to be hyped for 2019, but no, 2019 might, in fact, be the year that Blockchain dies. Let’s consider where we are right now: Blockchain, in itself, is a good idea. But so far all we’ve really had our various cryptocurrencies looking ever so slightly like pyramid schemes. Any further applications of Blockchain have, by and large, eluded the tech world. In fact, it’s become a useful sticker for organizations looking to raise funds - there are examples of apps out there that support Blockchain backed technologies in the early stages of funding which are later dropped as the company gains support. And it’s important to note that the word Blockchain doesn’t actually refer to one thing - there are many competing definitions as this article on The Verge explains so well. At risk of sounding flippant, Blockchain is ultimately a decentralized database. The reason it’s so popular is precisely because there is a demand for a database that is both scalable and available to a variety of parties - a database that isn’t surrounded by the implicit bureaucracy and politics that even the most prosaic ones do. From this perspective, it feels likely that 2019 will be a search for better ways of managing data - whether that includes Blockchain in its various forms remains to be seen. What you should learn instead of Blockchain A trend that some have seen as being related to Blockchain is edge computing. Essentially, this is all about decentralized data processing at the ‘edge’ of a network, as opposed to within a centralized data center (say, for example, cloud). Understanding the value of edge computing could allow us to better realise what Blockchain promises. Learn edge computing with Azure IoT Development Cookbook. It’s also worth digging deeper into databases - understanding how we can make these more scalable, reliable, and available, are essentially the tasks that anyone pursuing Blockchain is trying to achieve. So, instead of worrying about a buzzword, go back to what really matters. Get to grips with new databases. Learn with Seven NoSQL Databases in a Week Why I could be wrong about Blockchain There’s a lot of support for Blockchain across the industry, so it might well be churlish to dismiss it at this stage. Blockchain certainly does offer a completely new way of doing things, and there are potentially thousands of use cases. If you want to learn Blockchain, check out these titles: Mastering Blockchain, Second Edition Foundations of Blockchain Blockchain for Enterprise   Hadoop and big data If Blockchain is still receiving considerable hype, then big data has been slipping away quietly for the last couple of years. Of course, it hasn’t quite disappeared - data is now a normal part of reality. It’s just that trends like artificial intelligence and cloud have emerged to take its place and place even greater emphasis on what we’re actually doing with that data, and how we’re doing it. Read more: Why is Hadoop dying? With this change in emphasis, we’ve also seen the slow death of Hadoop. In a world that increasingly cloud native, it simply doesn’t make sense to run data on a cluster of computers - instead, leveraging public cloud makes much more sense. You might, for example, use Amazon S3 to store your data and then Spark, Flink, or Kafka for processing. Of course, the advantages of cloud are well documented. But in terms of big data, cloud allows for much greater elasticity in terms of scale, greater speed, and makes it easier to perform machine learning thanks to in built features that a number of the leading cloud vendors provide. What you should learn instead of Hadoop The future of big data largely rests in tools like Spark, Flink and Kafka. But it’s important to note it’s not really just about a couple of tools. As big data evolves, focus will need to be on broader architectural questions about what data you have, where it needs to be stored and how it should be used. Arguably, this is why ‘big data’ as a concept will lose valence with the wider community - it will still exist, but will be part of parcel of everyday reality, it won’t be separate from everything else we do. Learn the tools that will drive big data in the future: Apache Spark 2: Data Processing and Real-Time Analytics [Learning Path] Apache Spark: Tips, Tricks, & Techniques [Video] Big Data Processing with Apache Spark Learning Apache Flink Apache Kafka 1.0 Cookbook Why I could be wrong about Hadoop Hadoop 3 is on the horizon and could be the saving grace for Hadoop. Updates suggest that this new iteration is going to be much more amenable to cloud architectures. Learn Hadoop 3: Apache Hadoop 3 Quick Start Guide Mastering Hadoop 3         R 12 to 18 months ago debate was raging over whether R or Python was the best language for data. As we approach the end of 2018, that debate seems to have all but disappeared, with Python finally emerging as the go-to language for anyone working with data. There are a number of reasons for this: Python has the best libraries and frameworks for developing machine learning models. TensorFlow, for example, which runs on top of Keras, makes developing pretty sophisticated machine and deep learning systems relatively easy. R, however, simply can’t match Python in this way. With this ease comes increased adoption. If people want to ‘get into’ machine learning and artificial intelligence, Python is the obvious choice. This doesn’t mean R is dead - instead, it will continue to be a language that remains relevant for very specific use cases in research and data analysis. If you’re a researcher in a university, for example, you’ll probably be using R. But it at least now has to concede that it will never have the reach or levels of growth that Python has. What you should learn instead of R This is obvious - if you’re worried about R’s flexibility and adaptability for the future, you need to learn Python. But it’s certainly not the only option when it comes to machine learning - the likes of Scala and Go could prove useful assets on your CV, for machine learning and beyond. Learn a new way to tackle contemporary data science challenges: Python Machine Learning - Second Edition Hands-on Supervised Machine Learning with Python [Video] Machine Learning With Go Scala for Machine Learning - Second Edition       Why I could be wrong about R R is still an incredibly useful language when it comes to data analysis. Particularly if you’re working with statistics in a variety of fields, it’s likely that it will remain an important part of your skill set for some time. Check out these R titles: Getting Started with Machine Learning in R [Video] R Data Analysis Cookbook - Second Edition Neural Networks with R         IoT IoT is a term that has been hanging around for quite a while now. But it still hasn’t quite delivered on the hype that it originally received. Like Blockchain, 2019 is perhaps IoT’s make or break year. Even if it doesn’t develop into the sort of thing it promised, it could at least begin to break down into more practical concepts - like, for example edge computing. In this sense, we’d stop talking about IoT as if it were a single homogenous trend about to hit the modern world, but instead a set of discrete technologies that can produce new types of products, and complement existing (literal) infrastructure. The other challenge that IoT faces in 2019 is that the very concept of a connected world depends upon decision making - and policy - beyond the world of technology and business. If, for example, we’re going to have smart cities, there needs to be some kind of structure in place on which some degree of digital transformation can take place. Similarly, if every single device is to be connected in some way, questions will need to be asked about how these products are regulated and how this data is managed. Essentially, IoT is still a bit of a wild west. Given the year of growing scepticism about technology, major shifts are going to be unlikely over the next 12 months. What to learn One way of approaching IoT is instead to take a step back and think about the purpose of IoT, and what facets of it are most pertinent to what you want to achieve. Are you interested in collecting and analyzing data? Or developing products that have in built operational intelligence. Once you think about it from this perspective, IoT begins to sound less like a conceptual behemoth, and something more practical and actionable. Why I could be wrong about IoT Immediate shifts in IoT might be slow, but it could begin to pick up speed in organizations that understand it could have a very specific value. In this sense, IoT is a little like Blockchain - it’s only really going to work if we can move past the hype, and get into the practical uses of different technologies. Check out some of our latest IoT titles: Internet of Things Programming Projects Industrial Internet Application Development Introduction to Internet of Things [Video] Alexa Skills Projects       Does anything really die in tech? You might be surprised at some of the entries on this list - others, not so much. But either way, it’s worth pointing out that ultimately nothing ever really properly disappears in tech. From a legacy perspective change and evolution often happens slowly, and in terms of innovation buzzwords and hype don’t simply vanish, they mature and influence developments in ways we might not have initially expected. What will really be important in 2019 is to be alive to these shifts, and give yourself the best chance of taking advantage of change when it really matters.
Read more
  • 0
  • 0
  • 32552
Modal Close icon
Modal Close icon