{ "cells": [ { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Interpreting the output of `find_adversarial_example`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using the same example from the quickstart, we explore what information is available from the result of `find_adversarial_example`." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "┌ Info: Precompiling MIPVerify [e5e5f8be-2a6a-5994-adbb-5afbd0e30425]\n", "└ @ Base loading.jl:1260\n" ] } ], "source": [ "using MIPVerify\n", "using Gurobi\n", "using JuMP\n", "using Images\n", "\n", "mnist = MIPVerify.read_datasets(\"MNIST\")\n", "n1 = MIPVerify.get_example_network_params(\"MNIST.n1\")\n", "sample_image = MIPVerify.get_image(mnist.test.images, 1);\n", "\n", "function view_diff(diff::Array{<:Real, 2})\n", " n = 1001\n", " colormap(\"RdBu\", n)[ceil.(Int, (diff .+ 1) ./ 2 .* n)]\n", "end;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's take a look at the output dictionary that results from a solve." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Academic license - for non-commercial use only\n", "\u001b[36m[notice | MIPVerify]: Attempting to find adversarial example. Neural net predicted label is 8, target labels are [10]\u001b[39m\n", "\u001b[36m[notice | MIPVerify]: Determining upper and lower bounds for the input to each non-linear unit.\u001b[39m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32m Calculating upper bounds: 100%|███████████████████████| Time: 0:00:00\u001b[39m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Academic license - for non-commercial use only\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32m Calculating lower bounds: 100%|███████████████████████| Time: 0:00:00\u001b[39m\n", "\u001b[32m Imposing relu constraint: 100%|███████████████████████| Time: 0:00:00\u001b[39m\n", "\u001b[32m Calculating upper bounds: 10%|██▎ | ETA: 0:03:39\u001b[39m" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Academic license - for non-commercial use only\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32m Calculating upper bounds: 100%|███████████████████████| Time: 0:00:24\u001b[39m\n", "\u001b[32m Calculating lower bounds: 100%|███████████████████████| Time: 0:00:00\u001b[39m\n", "\u001b[32m Imposing relu constraint: 100%|███████████████████████| Time: 0:00:00\u001b[39m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Academic license - for non-commercial use only\n", "Academic license - for non-commercial use only\n" ] }, { "data": { "text/plain": [ "Dict{Any,Any} with 11 entries:\n", " :TargetIndexes => [10]\n", " :SolveTime => 15.6326\n", " :TotalTime => 62.0275\n", " :Perturbation => VariableRef[noname noname … noname noname]…\n", " :PerturbedInput => VariableRef[noname noname … noname noname]…\n", " :TighteningApproach => \"lp\"\n", " :PerturbationFamily => linf-norm-bounded-0.05\n", " :SolveStatus => OPTIMAL\n", " :Model => A JuMP Model…\n", " :Output => GenericAffExpr{Float64,VariableRef}[-0.012063867412507…\n", " :PredictedIndex => 8" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1 = MIPVerify.find_adversarial_example(\n", " n1, \n", " sample_image, \n", " 10, \n", " Gurobi.Optimizer,\n", " # OutputFlag=0 prevents any output from being printed out\n", " Dict(\"OutputFlag\" => 0),\n", " pp = MIPVerify.LInfNormBoundedPerturbationFamily(0.05),\n", " norm_order = Inf,\n", " tightening_algorithm = lp,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `:Model`\n", "\n", "The model stores a lot of information. (Remember not to try to print large models!) " ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "m = d1[:Model];" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here are some `JuMP` methods you might find useful." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2411" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "num_variables(m)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2381" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "num_constraints(m, VariableRef, MOI.GreaterThan{Float64})" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "15.632591009140015" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "solve_time(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this case, the lower bound on the objective and the best value we found is the same (but it can be different if we set time or other user limits)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.046084681588922705" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "objective_bound(m)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.046084681588922705" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "objective_value(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `:PerturbationFamily`\n", "\n", "Information on the family of perturbations we are searching over is stored in `:PerturbationFamily`." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "linf-norm-bounded-0.05" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1[:PerturbationFamily]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `:TargetIndexes`\n", "\n", "The perturbed image is guaranteed to be classified in one of the target indexes. (Strictly speaking, we guarantee that the highest activation in the output layer among the target indexes is at least highest activation in the output layer among non-target indexes within a small numeric tolerance)." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1-element Array{Int64,1}:\n", " 10" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1[:TargetIndexes]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Multiple target labels and an inverted target selection are appropriately handled." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Academic license - for non-commercial use only\n", "\u001b[36m[notice | MIPVerify]: Attempting to find adversarial example. Neural net predicted label is 8, target labels are [1, 2, 3, 4, 5, 6, 7, 9, 10]\u001b[39m\n", "\u001b[36m[notice | MIPVerify]: Determining upper and lower bounds for the input to each non-linear unit.\u001b[39m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32m Calculating upper bounds: 100%|███████████████████████| Time: 0:00:00\u001b[39m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Academic license - for non-commercial use only\n", "Academic license - for non-commercial use only\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32m Calculating upper bounds: 100%|███████████████████████| Time: 0:00:00\u001b[39m\n", "\u001b[32m Calculating lower bounds: 100%|███████████████████████| Time: 0:00:00\u001b[39m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Academic license - for non-commercial use only\n", "Academic license - for non-commercial use only\n" ] }, { "data": { "text/plain": [ "9-element Array{Int64,1}:\n", " 1\n", " 2\n", " 3\n", " 4\n", " 5\n", " 6\n", " 7\n", " 9\n", " 10" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d2 = MIPVerify.find_adversarial_example(\n", " n1, \n", " sample_image, \n", " 8,\n", " Gurobi.Optimizer,\n", " # OutputFlag=0 prevents any output from being printed out\n", " Dict(\"OutputFlag\" => 0, \"TimeLimit\" => 5),\n", " pp = MIPVerify.LInfNormBoundedPerturbationFamily(0.05),\n", " norm_order = Inf,\n", " tightening_algorithm = lp,\n", " invert_target_selection = true,\n", ")\n", "d2[:TargetIndexes]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `:SolveStatus`\n", "\n", "This is the result of the solve. [More information on solve statuses](https://jump.dev/MathOptInterface.jl/stable/apireference/#MathOptInterface.TerminationStatusCode)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We typically find an optimal solution:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "OPTIMAL::TerminationStatusCode = 1" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1[:SolveStatus]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But we can encounter other solve statuses if (for instance) we set a time limit." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "TIME_LIMIT::TerminationStatusCode = 12" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d2[:SolveStatus]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `:Perturbation`\n", "\n", "This is the (pixel-wise) difference between the original image and the perturbed image." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1×28×28×1 Array{Float64,4}:\n", "[:, :, 1, 1] =\n", " 0.0460847 0.0 0.0 0.0460847 0.0 … 0.0 0.0 0.0 0.0 0.0 0.0460847\n", "\n", "[:, :, 2, 1] =\n", " 0.0 0.0 0.0 0.0460847 0.0460847 0.0 … 0.0 0.0 0.0 0.0 0.0460847\n", "\n", "[:, :, 3, 1] =\n", " 0.0 0.0 0.0 0.0 0.0 0.0 0.0460847 … 0.0 0.0 0.0460847 0.0 0.0\n", "\n", "...\n", "\n", "[:, :, 26, 1] =\n", " 0.0 0.0 0.0460847 0.0 0.0 0.0 0.0 … 0.0460847 0.0460847 0.0 0.0\n", "\n", "[:, :, 27, 1] =\n", " 0.0460847 0.0460847 0.0 0.0 0.0 0.0 … 0.0460847 0.0 0.0460847\n", "\n", "[:, :, 28, 1] =\n", " 0.0460847 0.0 0.0460847 0.0 0.0 0.0 … 0.0 0.0 0.0 0.0460847 0.0" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "perturbation = JuMP.value.(d1[:Perturbation])" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAHAAAABwBAMAAAA0zul4AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAJ1BMVEXp9v35+Pnr9/3s9/3/7+vx+v7/8Ovx+f7t+P3v+f7/9PH/9vP///9TFX8KAAAAAWJLR0QMgbNRYwAAAVxJREFUWMPVl0EVAjEMRGMBC1jAQi2sBSxgAQtYwALmoCxDJplyZ3KA3Sa/vDdJ2hARh49FzOeI+g1f+uHzAdmReA3PlYz0A+fL8ciypBC55elE0hmBPZcZyILouhNYJVhhnHpPsJf2b1Ta3gbUosZW6amt/G1kG5APpDEixtt6S1dp6JcsQF7csW0bYtM/htxVJiCnePywiO1lVUhPsC9P5HzmDbjlncB86VnlfS+XuREfZG6gqCS6qd8RZBe/zae9wFk0LxBOvUARer2iiZddYQDKdSkGadolZAf2IZ4NI3zzWoG8pAXP0iDCD1wPtnv47YZjmIdEPzDLIIthGoYl3ZDGXBNQ0Wn3O48MKpsT2NsZVrGe/sU58MfgWhpgj4deSOUEMAF5CWFdmm5tsjIBOdFoYYzvOgr7gdzO9c8ZF/9CHCOQ0wxx9suGsfz8HsgmYEqi7loY1W8EPgFw1YaIp86glAAAAABJRU5ErkJggg==", "text/plain": [ "28×28 Array{RGB{Float64},2} with eltype RGB{Float64}:\n", " RGB{Float64}(0.911923,0.96363,0.991867) … RGB{Float64}(0.911923,0.96363,0.991867)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.974944,0.972996,0.976035)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.911923,0.96363,0.991867)\n", " RGB{Float64}(0.911923,0.96363,0.991867) RGB{Float64}(0.974944,0.972996,0.976035)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.974944,0.972996,0.976035)\n", " RGB{Float64}(0.911923,0.96363,0.991867) … RGB{Float64}(0.974944,0.972996,0.976035)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.974944,0.972996,0.976035)\n", " RGB{Float64}(0.911923,0.96363,0.991867) RGB{Float64}(0.911923,0.96363,0.991867)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.911923,0.96363,0.991867)\n", " RGB{Float64}(0.911923,0.96363,0.991867) RGB{Float64}(0.974944,0.972996,0.976035)\n", " RGB{Float64}(0.911923,0.96363,0.991867) … RGB{Float64}(0.974944,0.972996,0.976035)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.974944,0.972996,0.976035)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.974944,0.972996,0.976035)\n", " ⋮ ⋱ \n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.911923,0.96363,0.991867)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.911923,0.96363,0.991867)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.911923,0.96363,0.991867)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.911923,0.96363,0.991867)\n", " RGB{Float64}(0.974944,0.972996,0.976035) … RGB{Float64}(0.911923,0.96363,0.991867)\n", " RGB{Float64}(0.911923,0.96363,0.991867) RGB{Float64}(0.974944,0.972996,0.976035)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.911923,0.96363,0.991867)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.974944,0.972996,0.976035)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.974944,0.972996,0.976035)\n", " RGB{Float64}(0.974944,0.972996,0.976035) … RGB{Float64}(0.974944,0.972996,0.976035)\n", " RGB{Float64}(0.974944,0.972996,0.976035) RGB{Float64}(0.911923,0.96363,0.991867)\n", " RGB{Float64}(0.911923,0.96363,0.991867) RGB{Float64}(0.974944,0.972996,0.976035)" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "view_diff(perturbation[1, :, :, 1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `:PerturbedInput`\n", "\n", "This is the perturbed image." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1×28×28×1 Array{Float64,4}:\n", "[:, :, 1, 1] =\n", " 0.0460847 0.0 0.0 0.0460847 0.0 … 0.0 0.0 0.0 0.0 0.0 0.0460847\n", "\n", "[:, :, 2, 1] =\n", " 0.0 0.0 0.0 0.0460847 0.0460847 0.0 … 0.0 0.0 0.0 0.0 0.0460847\n", "\n", "[:, :, 3, 1] =\n", " 0.0 0.0 0.0 0.0 0.0 0.0 0.0460847 … 0.0 0.0 0.0460847 0.0 0.0\n", "\n", "...\n", "\n", "[:, :, 26, 1] =\n", " 0.0 0.0 0.0460847 0.0 0.0 0.0 0.0 … 0.0460847 0.0460847 0.0 0.0\n", "\n", "[:, :, 27, 1] =\n", " 0.0460847 0.0460847 0.0 0.0 0.0 0.0 … 0.0460847 0.0 0.0460847\n", "\n", "[:, :, 28, 1] =\n", " 0.0460847 0.0 0.0460847 0.0 0.0 0.0 … 0.0 0.0 0.0 0.0460847 0.0" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "perturbed_input = JuMP.value.(d1[:PerturbedInput])" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAAAAADji6uXAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAALHSURBVGje7dq/r0xBFAfwz/LiVx4FiQh5OhIaEREFhY5QKJQaGhWN0EgU/gydSCQanYhQiB9BJRHxM2hQ0L4tJCQU915vdnbm7ja792WyJ9nszNxzZnK/35wzM+fc3jz6BmW+/u8H7Vw/tusn7MOxFaYs5S84F/IQ8hnzE4/PR/9abMPn5UM6fQ7DTuMvfwz7Upv/xf7ZzDEX9Bud8iGd+oK9kKtG2mJiTlIxN6VfPqTdxNIwLuZ8rD9iolxM7vwNy1+wF+I9yidH8SiaR8KmfEinzyGDmJM+T4Y89xM2Ir1YGrvyIZ1+LM1xcghX8BK/cLMe/5SZKPblcEzwrHxIu/FDhrH/iTV1fz0W69+blsm24Bsu4L20z5YPaXfn0lD6OIA9eIvd2IvD2IavWAj0/2AlNtT9a7gonRMoH9LlwSFp/BdUXN7BfpUT/1XF2o94h404hxu1Xbyflg9p97G07bzSPI9t4CSu4wt2YZX0ebZ8SLvjsJFx+It1NuM11uE0brfYlw9pt7k28n6Y46+Pqyr+fuNDxq6zNyx/wd44+bS22sVB3Kvbx/FYPt528oblLzhQtxjnHh+PHav/X+B5i97sTDMxGdgPc9zl+FyLp9iJI3iW0JndDycucwzXjVJxNcXjJRV/Tyzxl8vTzWrAE5OBu8U4Oe2Gi+O4he84gwfStarZfjhxGfLDlMT1/dW4XPfvqvhj2G9F/Vm+dCKSvOOPkofYh884ih8j9Gf74USll6sz5GLrVlU+G06o+Ixt2s5G5UPabR0/lBR/m3C/bl+yxF/DWdv3VM03OeVD2s1+mLqTx3dFOIvtdftRYDMqxxrOWT6kyyPX1kgYE3fgvKVaoowe7ZyWD2l3HOa+q2nGD9XtRdVZJnV3zOVUO33D8hf8z2EuTxr71CucUtXrY722dtMvH9LllfNu4yMl49iXD+nUF/wHg+y5HmmDeFIAAAAASUVORK5CYII=", "text/plain": [ "28×28 reinterpret(Gray{Float64}, ::Array{Float64,2}):\n", " Gray{Float64}(0.0460847) … Gray{Float64}(0.0460847)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0460847)\n", " Gray{Float64}(0.0460847) Gray{Float64}(0.0)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0)\n", " Gray{Float64}(0.0460847) … Gray{Float64}(0.0)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0)\n", " Gray{Float64}(0.0460847) Gray{Float64}(0.0460847)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0460847)\n", " Gray{Float64}(0.0460847) Gray{Float64}(0.0)\n", " Gray{Float64}(0.0460847) … Gray{Float64}(0.0)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0)\n", " ⋮ ⋱ \n", " Gray{Float64}(0.0) Gray{Float64}(0.0460847)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0460847)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0460847)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0460847)\n", " Gray{Float64}(0.0) … Gray{Float64}(0.0460847)\n", " Gray{Float64}(0.0460847) Gray{Float64}(0.0)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0460847)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0)\n", " Gray{Float64}(0.0) … Gray{Float64}(0.0)\n", " Gray{Float64}(0.0) Gray{Float64}(0.0460847)\n", " Gray{Float64}(0.0460847) Gray{Float64}(0.0)" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "colorview(Gray, perturbed_input[1, :, :, 1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can verify that the perturbed input is in fact the sample image added to the perturbation." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "false" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all(perturbed_input == sample_image + perturbation)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `:Output`\n", "\n", "This is the calculated value of the activations of the final layer of the neural net with the perturbed input. Note that `output[10]` is (tied for) the largest element of the array." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10-element Array{Float64,1}:\n", " 0.674945062874581\n", " 0.6179790360668656\n", " 0.3930321598089366\n", " 0.2965618596703666\n", " 0.24101053495483843\n", " 0.16060021203574887\n", " 0.5428526100447338\n", " 4.288351484573902\n", " -0.22643018233076873\n", " 4.288351484573896" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "output = JuMP.value.(d1[:Output])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can verify that these activations are indeed accurate:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10-element Array{Float64,1}:\n", " 0.6749450628745901\n", " 0.6179790360668731\n", " 0.39303215980894035\n", " 0.29656185967037274\n", " 0.24101053495484248\n", " 0.1606002120357537\n", " 0.5428526100447416\n", " 4.2883514845739015\n", " -0.22643018233076506\n", " 4.288351484573905" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "perturbed_input |> n1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Julia 1.4.2", "language": "julia", "name": "julia-1.4" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.4.2" } }, "nbformat": 4, "nbformat_minor": 2 }