<jupyter_start><jupyter_text>![entry.png](attachment:entry.png) RedisAI is a Redis module for serving tensors and executing deep learning models. While RedisAI takes care of making a runtime for your model by supporting tensor datatypes and manages downstream runtimes built on top of Tensorflow, PyTorch and ONNXRuntime, Redis itself helps you handle the scale, for which Redis is known for.Detailed blog: https://medium.com/tensorwerk/redisai-thors-stormbreaker-for-deep-learning-deployment-a3fe7569c559 But before we jumping in, let's take a step back and look into the current Deep Learning / Machine Learning world Deep Learning / Machine Learning - A precursor- Matrices / Tensors- Fundamental Operations- Regression, Classification, Neural Networks & Deep Networks- **Scikit Learn** example- **Tensorflow** example- **PyTorch** example<jupyter_code>import numpy as np
np.random.random((5, 2))
a = np.random.random((5, 7))
b = np.random.random((7, 2))
c = a @ b
print(f'On matrix multiplication: {c.shape}')

a = np.random.random((5, 3))
b = np.random.random((5, 3))
c = a + b
print(f'On addition: {c.shape}')

# Other math operations, activation functions etc<jupyter_output><empty_output><jupyter_text>Linear Regression with Scikit Learn![sklearn.png](attachment:sklearn.png)<jupyter_code>import sklearn
from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_boston
boston = load_boston()
x, y = boston.data, boston.target
print(boston.DESCR)
(x.shape, y.shape)
testindex = 25
testarray = x[testindex]
testtarget = y[testindex]
for i in range(len(boston.feature_names)):
    print(f'{boston.feature_names[i]:<10}: {testarray[i]}')
testtarget
model = LinearRegression()
model.fit(x, y)
model.predict(testarray.reshape(1, -1))
# needed later
sklearn_model = model<jupyter_output><empty_output><jupyter_text>Object Detection with Tensorflow![tensorflow.png](attachment:tensorflow.png)  Load graph and required variables<jupyter_code>import tensorflow as tf
# download the model from https://app.box.com/s/ottxnjxc1ev9wlqiw0gmsb87r9xzjkyd
frozen_graph = "../assets/yolo.pb"
with tf.gfile.GFile(frozen_graph, "rb") as f:
    restored_graph_def = tf.GraphDef()
    restored_graph_def.ParseFromString(f.read())
with tf.Graph().as_default() as graph:
    tf.import_graph_def(
        restored_graph_def,
        input_map=None,
        return_elements=None,
        name="")
inputs = graph.get_tensor_by_name('input_1:0')
image_shape = graph.get_tensor_by_name('input_image_shape:0')
boxes = graph.get_tensor_by_name('concat_11:0')
classes = graph.get_tensor_by_name('concat_13:0')<jupyter_output><empty_output><jupyter_text>Load image<jupyter_code>from PIL import Image, ImageDraw
image = '../assets/nightking.jpg'
img_jpg = Image.open(image)<jupyter_output><empty_output><jupyter_text>preprocess<jupyter_code>np_img = np.array(img_jpg)
img = np_img.astype(np.float32)
img = np.expand_dims(img, axis=0)
img /= 255.0
img.shape<jupyter_output><empty_output><jupyter_text>Run model<jupyter_code>with tf.Session(graph=graph) as sess:
    sess.run([tf.global_variables_initializer()])
    ret_b, ret_c = sess.run([boxes, classes], feed_dict={inputs: img, image_shape: np.array((416, 416))})
shape = np_img.shape<jupyter_output><empty_output><jupyter_text>Post process<jupyter_code>new_shape = 416
def post_process(classes, boxes, shapes=(416, 416)):
    pad_x = max(shapes[0] - shapes[1], 0) * (new_shape / max(shapes))
    pad_y = max(shapes[1] - shapes[0], 0) * (new_shape / max(shapes))
    unpad_h = new_shape - pad_y
    unpad_w = new_shape - pad_x 
    for ind, class_val in enumerate(classes):
        top, left, bottom, right = boxes[ind]
        top = ((top.astype('int32') - pad_y // 2) / unpad_h) * shapes[0]
        left = ((left.astype('int32') - pad_x // 2) / unpad_w) * shapes[1]
        bottom = ((bottom.astype('int32') - pad_y // 2) / unpad_h) * shapes[0]
        right = ((right.astype('int32') - pad_x // 2) / unpad_w) * shapes[1]
        yield left, top, right, bottom
ret_b.dtype<jupyter_output><empty_output><jupyter_text>Process output<jupyter_code>draw = ImageDraw.Draw(img_jpg)
for left, top, right, bottom in post_process(ret_c, ret_b, shape):
    draw.rectangle(((left, top), (right, bottom)), outline='green')
from IPython.display import display
display(img_jpg)<jupyter_output><empty_output><jupyter_text>Chatbot with PyTorch![pytorch.png](attachment:pytorch.png)  Importing torch<jupyter_code>import torch<jupyter_output><empty_output><jupyter_text>Utilities, helper constants etc.<jupyter_code>import json
import re

voc_file = '../assets/voc.json'
with open(voc_file)as f:
    voc_content = json.load(f)
    w2i = voc_content['word2index']
    i2w = voc_content['index2word']

PAD_token = 0
SOS_token = 1
EOS_token = 2
max_len = 30

def normalize_string(s):
    s = s.lower()
    s = re.sub(r"([.!?])", r" \1", s)
    s = re.sub(r"[^a-zA-Z.!?]+", r" ", s)
    return s

def str2indices(sentence):
    return [[el for el in [w2i.get(word) for word in sentence.split()] if el is not None] + [EOS_token]]

def indices2str(indices):
    return ' '.join([i2w[str(ind)] for ind in indices])<jupyter_output><empty_output><jupyter_text>Encoder & Decoder using PyTorch JIT<jupyter_code>encoder = torch.jit.load('../assets/encoder.pt')
decoder = torch.jit.load('../assets/decoder.pt')<jupyter_output><empty_output><jupyter_text>Processing input<jupyter_code>import numpy as np
d_input = torch.tensor(SOS_token, dtype=torch.int64).reshape(1, 1)
mysentence = "Are you crazy?"


indices = str2indices(normalize_string(mysentence))
array = torch.from_numpy(np.array(indices, dtype=np.long).transpose())
length = torch.from_numpy(np.array([len(array)], dtype=np.long))<jupyter_output><empty_output><jupyter_text>Running encoder & decoder<jupyter_code>e_out, hidden = encoder(array, length)
decoder_out = []
for i in range(max_len):
    out, hidden = decoder(d_input, hidden, e_out)
    spanned_out = out.reshape(1, -1)
    ind = spanned_out.argmax(1).item()
    if ind == EOS_token:
        break
    d_input = torch.tensor(ind, dtype=torch.int64).reshape(1, 1)
    if ind == PAD_token:
        continue
    decoder_out.append(ind)<jupyter_output><empty_output><jupyter_text>Processing output<jupyter_code>print(indices2str(decoder_out))<jupyter_output><empty_output><jupyter_text>What do we cover today?![Screenshot%20from%202019-07-25%2010-16-51.png](attachment:Screenshot%20from%202019-07-25%2010-16-51.png)  Getting Started with RedisAIWe'll start with installing RedisAI. Setting it up in a bare machine is few lines of commands and even for scaling it up for millions request per second, couple of config changes should be good enough.You can find the examples at https://github.com/RedisAI/redisai-examples A quick introduction about the features of RedisAI?? Setting up a new machine```bashsudo apt update sudo apt install -y build-essential tcl libjemalloc-dev git cmake unzipsudo ufw allow 6379sudo ufw allow 26379``` Installing Redis```bashcurl -O http://download.redis.io/redis-stable.tar.gztar xzvf redis-stable.tar.gzcd redis-stablemakesudo make installcd ~rm redis-stable.tar.gz``` Building RedisAI module```bashgit clone https://github.com/RedisAI/RedisAI.gitcd RedisAIbash get_deps.sh cpumkdir buildcd buildcmake -DDEPS_PATH=../deps/install ..makecd ..```  However ...```bashdocker run -p 6379:6379 -it --rm redisai/redisai```  Client Libraries  redis-cli```bash Setting a tensor using redis-cliAI.TENSORSET foo FLOAT 2 2 VALUES 1 2 3 4``` Python Redis client```python Setting a tensor using python Redis clientimport redisr = redis.Redis(host='localhost', port=6379)r.execute_command('AI.TENSORSET', 'foo', 'FLOAT', 2, 2, 'VALUES', 1, 2, 3, 4)``` Python RedisAI client```python Setting a tensor using Python RedisAI clientimport redisai as raicon = rai.Client(host='localhost', port=6379)foo = rai.Tensor(rai.DType.float, [2, 2], [1, 2, 3, 4])con.tensorset('foo', foo)``` NodeJS Redis client```node// Setting a tensor using NodeJS Redis clientvar Redis = require('ioredis')let redis = new Redis({ parser: 'javascript' });redis.call('AI.TENSORSET','foo','FLOAT',2,2,'VALUES',1,2,3,4)``` Go Redis client```go// Setting a tensor using GoLang Redis clientpackage mainimport "github.com/go-redis/redis"func main() {    client := redis.NewClient(&redis.Options{            Addr:     "localhost:6379",            Password: "",        })          client.Do("AI.TENSORSET","foo","FLOAT",2,2,"VALUES",1,2,3,4)}```<jupyter_code>import redisai as rai
con = rai.Client(host='localhost', port=6379)
foo = rai.Tensor(rai.DType.float, [2, 2], [1, 2, 3, 4])
con.tensorset('foo', foo)<jupyter_output><empty_output><jupyter_text>A quick glimpse into redisai python client<jupyter_code>import redisai<jupyter_output><empty_output><jupyter_text>ValueTensor and BlobTensor<jupyter_code>con = redisai.Client(host='localhost', port=6379)
foo = rai.Tensor(rai.DType.float, [2, 2], [1, 2, 3, 4])
con.tensorset('foo', foo)
import numpy as np
random_array = np.random.random((3, 4))
foo = redisai.BlobTensor.from_numpy(random_array)
con.tensorset('foo', foo)<jupyter_output><empty_output><jupyter_text>Modelset & Scriptset```pythoncon.modelset('whaaaaaaaaaat?')con.scriptset('whaaaaaaaaat again??')```  ml2rt<jupyter_code>import ml2rt
# prototype=x[0].reshape(1, -1).astype(np.float32) what is this?
# shape=(1, 13), dtype=np.float32, what is this?
# ml2rt.utils.guess_onnx_tensortype(x[0].reshape(1, -1).astype(np.float32))
# initial_types=[ml2rt.utils.guess_onnx_tensortype(x[0].reshape(1, -1).astype(np.float32))]


ml2rt.save_sklearn(sklearn_model, '../assets/boston.onnx')
dir(ml2rt)
sklearn_model = ml2rt.load_model('../assets/boston.onnx')
con.modelset('sklearn', redisai.Backend.onnx, redisai.Device.cpu, sklearn_model)
con.modelrun('Not now!!')
script_string = '''
def add_two(a, b):
    return a + b

'''
con.scriptset('script', redisai.Device.cpu, script_string)
tensor = redisai.BlobTensor.from_numpy(np.array([1, 2]))

con.tensorset('a', tensor)
con.tensorset('b', tensor)
con.scriptrun('script', 'add_two', input=['a', 'b'], output='c')
ret = con.tensorget('c')
ret
ret = con.tensorget('c', as_type=redisai.BlobTensor)
ret.to_numpy()<jupyter_output><empty_output><jupyter_text>Enough of that!! Let's run through our examples-------------------------------------------------------------------------- Logistic regression with scikit-learn<jupyter_code>sklearn_model = ml2rt.load_model('../assets/boston.onnx')
con.modelset('sklearn', redisai.Backend.onnx, redisai.Device.cpu, sklearn_model)
tensor = redisai.BlobTensor.from_numpy(x[testindex].reshape(1, -1).astype(np.float32))
con.tensorset('input', tensor)
con.modelrun('sklearn', input='input', output='out')
con.tensorget('out').value<jupyter_output><empty_output><jupyter_text>Object Detection with Tensorflow<jupyter_code>yolomodel = ml2rt.load_model('../assets/yolo.pb')
# input=['input_1', 'input_image_shape'], output=['concat_11', 'concat_13']
con.modelset('yolo', redisai.Backend.tf, redisai.Device.cpu, yolomodel)
image = '../assets/nightking.jpg'
img_jpg = Image.open(image)
script = '''

def normalize(img):
    img /= 255
    return img

def pre_process(img):
    img = img.float()
    img = img.unsqueeze(0)
    normalize(img)
    return img
'''
# A common error point
con.scriptset('script', redisai.Device.cpu, script)
tensor = redisai.BlobTensor.from_numpy(np.array(img_jpg))
img_new_size = redisai.Tensor(redisai.DType.float, (2,), (416, 416))
con.tensorset('image', tensor)
con.tensorset('input_size', img_new_size)
con.scriptrun('script', 'pre_process', 'image', 'processed_image')
con.tensorget('processed_image', as_type=redisai.BlobTensor)
con.modelrun('yolo', input=['processed_image', 'input_size'], output=['boxes', 'classes'])
boxes = con.tensorget('boxes', as_type=redisai.BlobTensor).to_numpy()
classes = con.tensorget('classes', as_type=redisai.BlobTensor).to_numpy()
coordinates = post_process(classes, boxes)
for left, top, right, bottom in coordinates:
    draw.rectangle(((left, top), (right, bottom)), outline='green')

draw = ImageDraw.Draw(img_jpg)
display(img_jpg)<jupyter_output><empty_output><jupyter_text>Chatbot with PyTorch<jupyter_code>encoder = ml2rt.load_model('../assets/encoder.pt')
decoder = ml2rt.load_model('../assets/decoder.pt')
mysentence = "I don't like this people"

indices = str2indices(normalize_string(mysentence))
np_array = np.array(indices, dtype=np.long).transpose()
array = redisai.BlobTensor.from_numpy(np_array)
length = redisai.BlobTensor.from_numpy(np.array([len(np_array)], dtype=np.long))
d_input = redisai.Tensor(value=SOS_token, dtype=redisai.DType.int64, shape=(1, 1))
con.modelset('encoder', redisai.Backend.torch, redisai.Device.cpu, encoder)
con.modelset('decoder', redisai.Backend.torch, redisai.Device.cpu, decoder)
con.tensorset('sentence', array)
con.tensorset('length', length)
con.tensorset('d_input', d_input)
con.modelrun('encoder', input=['sentence', 'length'], output=['e_out', 'hidden'])
decoder_out = []
for i in range(max_len):
    # Don't have to carry around `hidden` and `e_out`
    con.modelrun('decoder', input=['d_input', 'hidden', 'e_out'], output=['out', 'hidden'])
    out = con.tensorget('out', as_type=redisai.BlobTensor).to_numpy()
    spanned_out = out.reshape(1, -1)
    ind = spanned_out.argmax().item()
    if ind == EOS_token:
        break
    d_input = redisai.Tensor(value=ind, dtype=redisai.DType.int64, shape=(1, 1))
    con.tensorset('d_input', d_input)
    if ind == PAD_token:
        continue
    decoder_out.append(ind)
indices2str(decoder_out)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1534442154842508, 'fraction_numerical': 0.02178392699440683, 'mean_word_length': 5.641739980449658, 'pattern_counts': {'":': 0, '<': 86, '<?xml version=': 0, '>': 85, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '21', 'dir': 'jupyter-structured-clean-dedup', 'id': '436438', 'license': 'Apache-2.0', 'n_tokens_mistral': 5103, 'n_tokens_neox': 4880, 'n_words': 991, 'path': 'src/tutorial.ipynb', 'repo_name': 'hhsecond/fifthel19', 'size': '13588'}