from pymldb import Connection
mldb = Connection()

import pandas as pd

"""
Explanation: KDNuggets Transfer Learning Blog Post
This is the companion notebook to the MLDB.ai guest blog post on KGNuggets.
The post will soon be published. If you want to try an interactive version of this notebook, simply signup for a free account.
Import some libraries
End of explanation
"""


print mldb.put('/v1/functions/inception', {
    "type": 'tensorflow.graph',
    "params": {
        "modelFileUrl": 'archive+'+
            'file://mldb/mldb_test_data/models/inception_dec_2015.zip'+
            '#tensorflow_inception_graph.pb',
        "inputs": 'fetcher(url)[content] AS "DecodeJpeg/contents"',
        "outputs": "pool_3"
    }
})

"""
Explanation: Inception on MLDB
We start by creating the inception function that we can call to run the trained Inception-V3 TensorFlow model:
End of explanation
"""


kdNuggets = "http://www.skytree.net/wp-content/uploads/2014/08/KDnuggets.jpg"

mldb.query("SELECT inception({url: '%s'}) as *" % kdNuggets)

"""
Explanation: We can then use it to embed any image in the representation it learned. Let's try doing this to the KDNuggets logo:
<img src="http://www.skytree.net/wp-content/uploads/2014/08/KDnuggets.jpg">
End of explanation
"""


print mldb.post("/v1/procedures", {
    "type": "import.text",
    "params": {
        "dataFileUrl": "file://mldb/mldb_test_data/datasets/car_brand_images/cars_urls.csv",
        "outputDataset": "images"
    }
})

mldb.query("SELECT * FROM images LIMIT 3")

"""
Explanation: Loading our dataset
We now load a CSV dataset that contains links to car images from three brands:
End of explanation
"""


mldb.query("SELECT count(*) FROM images GROUP BY brand")

"""
Explanation: Let's get a sense of how many images we have in each class:
End of explanation
"""


mldb.query("SELECT inception({url: url}) AS * FROM images LIMIT 3")

"""
Explanation: We can easily run a few images through the network like this:
End of explanation
"""


print mldb.post("/v1/procedures", {
    "type": "transform",
    "params": {
        "inputData": """
            SELECT brand,
                   inception({url}) as *
            FROM images
        """,
        "outputDataset": "training_dataset"
    }
})

"""
Explanation: To create our training dataset, we run a transform procedure to apply the TensorFlow model to all images:
End of explanation
"""


mldb.query("SELECT * FROM training_dataset LIMIT 3")

"""
Explanation: This gives us the following result:
End of explanation
"""


rez = mldb.post("/v1/procedures", {
    "type": "classifier.experiment",
    "params": {
        "experimentName": "car_brand_cls",
        "inputData": """        
            SELECT 
                {* EXCLUDING(brand)} as features,
                brand as label
            FROM training_dataset
        """,
        "mode": "categorical",
        "modelFileUrlPattern": "file:///mldb_data/car_brand_cls.cls",
         "configuration": {
            "type": "bagging",
            "weak_learner": {
                "type": "boosting",
                "weak_learner": {
                    "type": "decision_tree",
                    "max_depth": 5,
                    "update_alg": "gentle",
                    "random_feature_propn": 0.6
                },
                "min_iter": 5,
                "max_iter": 30
            },
            "num_bags": 15
        }
    }
})

runResults = rez.json()["status"]["firstRun"]["status"]["folds"][0]["resultsTest"]
print rez

"""
Explanation: Training a classifier
Let's now train a model. We'll use a 50/50 split for training and testing, and use a random forest:
End of explanation
"""


pd.DataFrame(runResults["confusionMatrix"])\
    .pivot_table(index="actual", columns="predicted", fill_value=0)

pd.DataFrame.from_dict(runResults["labelStatistics"]).transpose()

"""
Explanation: Let's look at our results on the test set:
End of explanation
"""


print mldb.put("/v1/functions/brand_predictor", {
    "type": "sql.expression",
    "params": {
        "expression": """
            car_brand_cls_scorer_0(
                {
                    features: inception({url})
                }) as *
        """
    }
})

"""
Explanation: Creating a real-time endpoint
We create a function of type sql.expression that will represent our pipeline and that we call brand_predictor. It takes the URL to an image, passes it through the inception model to extract the features, and then into the car_brand_cls_scorer_0 function that represents our trained model and that was created at the previous step.
End of explanation
"""


# good tesla: http://www.automobile-propre.com/wp-content/uploads/2016/09/tesla-premiere-livraison-france-657x438.jpg
# good tesla: http://insideevs.com/wp-content/uploads/2016/03/JL82776-750x500.jpg
# good bmw: http://www.bmwhk.com/content/dam/bmw/common/all-models/1-series/5-door/2015/images-and-videos/bmw-1-series-wallpaper-1920x1200-03-R.jpg/jcr:content/renditions/cq5dam.resized.img.485.low.time1448014414633.jpg

mldb.get("/v1/functions/brand_predictor/application", 
         data={'input': 
               {'url': 'http://insideevs.com/wp-content/uploads/2016/03/JL82776-750x500.jpg'}})

"""
Explanation: We can now call this endpoint on new images and get predictions back:
End of explanation
"""


