changeset 452:f339e3d5cc8c

finish draft of chapter 3.
author Robert McIntyre <rlm@mit.edu>
date Wed, 26 Mar 2014 22:17:42 -0400
parents 0a4362d1f138
children 6db37c4aa1ee
files org/self_organizing_touch.clj thesis/cortex.org thesis/images/touch-learn.png thesis/images/worm-roll.png thesis/rlm-cortex-meng.tex
diffstat 5 files changed, 270 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/org/self_organizing_touch.clj	Wed Mar 26 20:38:17 2014 -0400
     1.2 +++ b/org/self_organizing_touch.clj	Wed Mar 26 22:17:42 2014 -0400
     1.3 @@ -28,14 +28,14 @@
     1.4  
     1.5  (defn touch-kinesthetics []
     1.6    [[170 :lift-1 40]
     1.7 -   [190 :lift-1 20]
     1.8 +   [190 :lift-1 19]
     1.9     [206 :lift-1  0]
    1.10  
    1.11     [400 :lift-2 40]
    1.12     [410 :lift-2  0]
    1.13  
    1.14     [570 :lift-2 40]
    1.15 -   [590 :lift-2 20]
    1.16 +   [590 :lift-2 21]
    1.17     [606 :lift-2  0]
    1.18  
    1.19     [800 :lift-1 30]
    1.20 @@ -57,10 +57,18 @@
    1.21  (defn single-worm-segment []
    1.22    (load-blender-model "Models/worm/worm-single-segment.blend"))
    1.23  
    1.24 +(defn worm-segment []
    1.25 +  (let [model (single-worm-segment)]
    1.26 +    {:body (doto model (body!))
    1.27 +     :touch (touch! model)
    1.28 +     :proprioception (proprioception! model)
    1.29 +     :muscles (movement! model)}))
    1.30 +
    1.31 +
    1.32  (defn worm-segment-defaults []
    1.33    (let [direct-control (worm-direct-control worm-muscle-labels 40)]
    1.34      (merge (worm-world-defaults)
    1.35 -           {:worm-model single-worm-segment
    1.36 +           {:worm worm-segment
    1.37              :view single-worm-segment-view
    1.38              :experience-watch nil
    1.39              :motor-control
    1.40 @@ -97,23 +105,27 @@
    1.41     (rect-region [8   0] [14 29])
    1.42     (rect-region [15 15] [22 22])))
    1.43  
    1.44 -(defn view-touch-region [coords]
    1.45 -  (let [touched-region
    1.46 -        (reduce
    1.47 -         (fn [m k]
    1.48 -           (assoc m k [0.0 0.1]))
    1.49 -         (zipmap all-touch-coordinates (repeat [0.1 0.1])) coords)
    1.50 -        data
    1.51 -        [[(vec (keys touched-region)) (vec (vals touched-region))]]
    1.52 -        touch-display (view-touch)]
    1.53 -    (dorun (repeatedly 5 #(touch-display data)))))
    1.54 +(defn view-touch-region
    1.55 +  ([coords out]
    1.56 +     (let [touched-region
    1.57 +           (reduce
    1.58 +            (fn [m k]
    1.59 +              (assoc m k [0.0 0.1]))
    1.60 +            (zipmap all-touch-coordinates (repeat [0.1 0.1])) coords)
    1.61 +           data
    1.62 +           [[(vec (keys touched-region)) (vec (vals touched-region))]]
    1.63 +           touch-display (view-touch)]
    1.64 +       (touch-display data out)))
    1.65 +  ([coords] (view-touch-region nil)))
    1.66 +
    1.67  
    1.68  (defn learn-touch-regions []
    1.69    (let [experiences (atom [])
    1.70          world (apply-map
    1.71                 worm-world
    1.72                 (assoc (worm-segment-defaults)
    1.73 -                 :experiences experiences))]
    1.74 +                 :experiences experiences
    1.75 +                 :record (File. "/home/r/proj/cortex/thesis/video/touch-learn-2/")))]
    1.76      (run-world world)
    1.77      (->>
    1.78       @experiences
    1.79 @@ -132,6 +144,24 @@
    1.80       (map set)
    1.81       remove-similar)))
    1.82  
    1.83 +
    1.84 +(def all-touch-coordinates
    1.85 +  (concat
    1.86 +   (rect-region [0  15] [7  22])
    1.87 +   (rect-region [8   0] [14 29])
    1.88 +   (rect-region [15 15] [22 22])))
    1.89 +
    1.90 +(defn view-touch-region [coords]
    1.91 +  (let [touched-region
    1.92 +        (reduce
    1.93 +         (fn [m k]
    1.94 +           (assoc m k [0.0 0.1]))
    1.95 +         (zipmap all-touch-coordinates (repeat [0.1 0.1])) coords)
    1.96 +        data
    1.97 +        [[(vec (keys touched-region)) (vec (vals touched-region))]]
    1.98 +        touch-display (view-touch)]
    1.99 +    (dorun (repeatedly 5 #(touch-display data)))))
   1.100 +
   1.101  (defn learn-and-view-touch-regions []
   1.102    (map view-touch-region
   1.103         (learn-touch-regions)))
     2.1 --- a/thesis/cortex.org	Wed Mar 26 20:38:17 2014 -0400
     2.2 +++ b/thesis/cortex.org	Wed Mar 26 22:17:42 2014 -0400
     2.3 @@ -211,7 +211,8 @@
     2.4     #+caption: full circle. Imagine how you would replicate this functionality
     2.5     #+caption: using low-level pixel features such as HOG filters!
     2.6     #+name: grand-circle-intro
     2.7 -   #+begin_listing clojure
     2.8 +   #+attr_latex: [htpb]
     2.9 +#+begin_listing clojure
    2.10     #+begin_src clojure
    2.11  (defn grand-circle?
    2.12    "Does the worm form a majestic circle (one end touching the other)?"
    2.13 @@ -400,7 +401,7 @@
    2.14       :muscles (movement! model)}))
    2.15    #+end_src
    2.16    #+end_listing
    2.17 -  
    2.18 +
    2.19  ** Embodiment factors action recognition into managable parts
    2.20  
    2.21     Using empathy, I divide the problem of action recognition into a
    2.22 @@ -436,7 +437,8 @@
    2.23     #+caption: independent and ignores vermopomorphic differences such as 
    2.24     #+caption: worm textures and colors.
    2.25     #+name: curled
    2.26 -   #+begin_listing clojure
    2.27 +   #+attr_latex: [htpb]
    2.28 +#+begin_listing clojure
    2.29     #+begin_src clojure
    2.30  (defn curled?
    2.31    "Is the worm curled up?"
    2.32 @@ -451,7 +453,9 @@
    2.33     #+caption: Program for summarizing the touch information in a patch 
    2.34     #+caption: of skin.
    2.35     #+name: touch-summary
    2.36 -   #+begin_listing clojure
    2.37 +   #+attr_latex: [htpb]
    2.38 +
    2.39 +#+begin_listing clojure
    2.40     #+begin_src clojure
    2.41  (defn contact
    2.42    "Determine how much contact a particular worm segment has with
    2.43 @@ -476,7 +480,8 @@
    2.44     #+caption: floor. Note that this function contains no references to 
    2.45     #+caption: proprioction at all.
    2.46     #+name: resting
    2.47 -   #+begin_listing clojure
    2.48 +   #+attr_latex: [htpb]
    2.49 +#+begin_listing clojure
    2.50     #+begin_src clojure
    2.51  (def worm-segment-bottom (rect-region [8 15] [14 22]))
    2.52  
    2.53 @@ -495,7 +500,8 @@
    2.54     #+caption: I am able to both use a previous action predicate (=curled?=)
    2.55     #+caption: as well as the direct tactile experience of the head and tail.
    2.56     #+name: grand-circle
    2.57 -   #+begin_listing clojure
    2.58 +   #+attr_latex: [htpb]
    2.59 +#+begin_listing clojure
    2.60     #+begin_src clojure
    2.61  (def worm-segment-bottom-tip (rect-region [15 15] [22 22]))
    2.62  
    2.63 @@ -525,7 +531,8 @@
    2.64     #+caption: wiggle but can't. Frustrated wiggling is very visually different 
    2.65     #+caption: from actual wiggling, but this definition gives it to us for free.
    2.66     #+name: wiggling
    2.67 -   #+begin_listing clojure
    2.68 +   #+attr_latex: [htpb]
    2.69 +#+begin_listing clojure
    2.70     #+begin_src clojure
    2.71  (defn fft [nums]
    2.72    (map
    2.73 @@ -565,7 +572,8 @@
    2.74     #+caption: Use the action predicates defined earlier to report on 
    2.75     #+caption: what the worm is doing while in simulation.
    2.76     #+name: report-worm-activity
    2.77 -   #+begin_listing clojure
    2.78 +   #+attr_latex: [htpb]
    2.79 +#+begin_listing clojure
    2.80     #+begin_src clojure
    2.81  (defn debug-experience
    2.82    [experiences text]
    2.83 @@ -683,7 +691,8 @@
    2.84     #+caption: Program to convert an experience vector into a 
    2.85     #+caption: proprioceptively binned lookup function.
    2.86     #+name: bin
    2.87 -   #+begin_listing clojure
    2.88 +   #+attr_latex: [htpb]
    2.89 +#+begin_listing clojure
    2.90     #+begin_src clojure
    2.91  (defn bin [digits]
    2.92    (fn [angles]
    2.93 @@ -741,7 +750,8 @@
    2.94     #+caption: and finding the longest (ie. most coherent) interpretation
    2.95     #+caption: of the data.
    2.96     #+name: longest-thread
    2.97 -   #+begin_listing clojure
    2.98 +   #+attr_latex: [htpb]
    2.99 +#+begin_listing clojure
   2.100     #+begin_src clojure
   2.101  (defn longest-thread
   2.102    "Find the longest thread from phi-index-sets. The index sets should
   2.103 @@ -783,7 +793,8 @@
   2.104     #+caption: Fill in blanks in sensory experience by replicating the most 
   2.105     #+caption: recent experience.
   2.106     #+name: infer-nils
   2.107 -   #+begin_listing clojure
   2.108 +   #+attr_latex: [htpb]
   2.109 +#+begin_listing clojure
   2.110     #+begin_src clojure
   2.111  (defn infer-nils
   2.112    "Replace nils with the next available non-nil element in the
   2.113 @@ -804,19 +815,21 @@
   2.114     
   2.115     To use =EMPATH= with the worm, I first need to gather a set of
   2.116     experiences from the worm that includes the actions I want to
   2.117 -   recognize. The =generate-phi-space= program (listint
   2.118 +   recognize. The =generate-phi-space= program (listing
   2.119     \ref{generate-phi-space} runs the worm through a series of
   2.120     exercices and gatheres those experiences into a vector. The
   2.121     =do-all-the-things= program is a routine expressed in a simple
   2.122 -   muscle contraction script language for automated worm control.
   2.123 +   muscle contraction script language for automated worm control. It
   2.124 +   causes the worm to rest, curl, and wiggle over about 700 frames
   2.125 +   (approx. 11 seconds).
   2.126  
   2.127     #+caption: Program to gather the worm's experiences into a vector for 
   2.128     #+caption: further processing. The =motor-control-program= line uses
   2.129     #+caption: a motor control script that causes the worm to execute a series
   2.130     #+caption: of ``exercices'' that include all the action predicates.
   2.131     #+name: generate-phi-space
   2.132 -   #+attr_latex: [!H]
   2.133 -   #+begin_listing clojure 
   2.134 +   #+attr_latex: [htpb]
   2.135 +#+begin_listing clojure 
   2.136     #+begin_src clojure
   2.137  (def do-all-the-things 
   2.138    (concat
   2.139 @@ -843,7 +856,8 @@
   2.140     #+caption: Use longest thread and a phi-space generated from a short
   2.141     #+caption: exercise routine to interpret actions during free play.
   2.142     #+name: empathy-debug
   2.143 -   #+begin_listing clojure
   2.144 +   #+attr_latex: [htpb]
   2.145 +#+begin_listing clojure
   2.146     #+begin_src clojure
   2.147  (defn init []
   2.148    (def phi-space (generate-phi-space))
   2.149 @@ -891,7 +905,8 @@
   2.150     #+caption: Determine how closely empathy approximates actual 
   2.151     #+caption: sensory data.
   2.152     #+name: test-empathy-accuracy
   2.153 -   #+begin_listing clojure
   2.154 +   #+attr_latex: [htpb]
   2.155 +#+begin_listing clojure
   2.156     #+begin_src clojure
   2.157  (def worm-action-label
   2.158    (juxt grand-circle? curled? wiggling?))
   2.159 @@ -931,6 +946,7 @@
   2.160  
   2.161     #+caption: Program to generate \Phi-space using manual training.
   2.162     #+name: manual-phi-space
   2.163 +   #+attr_latex: [htpb]
   2.164     #+begin_listing clojure
   2.165     #+begin_src clojure
   2.166  (defn init-interactive []
   2.167 @@ -949,11 +965,174 @@
   2.168  
   2.169    After about 1 minute of manual training, I was able to achieve 95%
   2.170    accuracy on manual testing of the worm using =init-interactive= and
   2.171 -  =test-empathy-accuracy=. The ability of the system to infer sensory
   2.172 -  states is truly impressive.
   2.173 +  =test-empathy-accuracy=. The majority of errors are near the
   2.174 +  boundaries of transitioning from one type of action to another.
   2.175 +  During these transitions the exact label for the action is more open
   2.176 +  to interpretation, and dissaggrement between empathy and experience
   2.177 +  is more excusable.
   2.178  
   2.179  ** Digression: bootstrapping touch using free exploration
   2.180  
   2.181 +   In the previous section I showed how to compute actions in terms of
   2.182 +   body-centered predicates which relied averate touch activation of
   2.183 +   pre-defined regions of the worm's skin. What if, instead of recieving
   2.184 +   touch pre-grouped into the six faces of each worm segment, the true
   2.185 +   topology of the worm's skin was unknown? This is more similiar to how
   2.186 +   a nerve fiber bundle might be arranged. While two fibers that are
   2.187 +   close in a nerve bundle /might/ correspond to two touch sensors that
   2.188 +   are close together on the skin, the process of taking a complicated
   2.189 +   surface and forcing it into essentially a circle requires some cuts
   2.190 +   and rerragenments.
   2.191 +   
   2.192 +   In this section I show how to automatically learn the skin-topology of
   2.193 +   a worm segment by free exploration. As the worm rolls around on the
   2.194 +   floor, large sections of its surface get activated. If the worm has
   2.195 +   stopped moving, then whatever region of skin that is touching the
   2.196 +   floor is probably an important region, and should be recorded.
   2.197 +   
   2.198 +   #+caption: Program to detect whether the worm is in a resting state 
   2.199 +   #+caption: with one face touching the floor.
   2.200 +   #+name: pure-touch
   2.201 +   #+begin_listing clojure
   2.202 +   #+begin_src clojure
   2.203 +(def full-contact [(float 0.0) (float 0.1)])
   2.204 +
   2.205 +(defn pure-touch?
   2.206 +  "This is worm specific code to determine if a large region of touch
   2.207 +   sensors is either all on or all off."
   2.208 +  [[coords touch :as touch-data]]
   2.209 +  (= (set (map first touch)) (set full-contact)))
   2.210 +   #+end_src
   2.211 +   #+end_listing
   2.212 +
   2.213 +   After collecting these important regions, there will many nearly
   2.214 +   similiar touch regions. While for some purposes the subtle
   2.215 +   differences between these regions will be important, for my
   2.216 +   purposes I colapse them into mostly non-overlapping sets using
   2.217 +   =remove-similiar= in listing \ref{remove-similiar}
   2.218 +
   2.219 +   #+caption: Program to take a lits of set of points and ``collapse them''
   2.220 +   #+caption: so that the remaining sets in the list are siginificantly 
   2.221 +   #+caption: different from each other. Prefer smaller sets to larger ones.
   2.222 +   #+name: remove-similiar
   2.223 +   #+begin_listing clojure
   2.224 +   #+begin_src clojure
   2.225 +(defn remove-similar
   2.226 +  [coll]
   2.227 +  (loop [result () coll (sort-by (comp - count) coll)]
   2.228 +    (if (empty? coll) result
   2.229 +        (let  [[x & xs] coll
   2.230 +               c (count x)]
   2.231 +          (if (some
   2.232 +               (fn [other-set]
   2.233 +                 (let [oc (count other-set)]
   2.234 +                   (< (- (count (union other-set x)) c) (* oc 0.1))))
   2.235 +               xs)
   2.236 +            (recur result xs)
   2.237 +            (recur (cons x result) xs))))))
   2.238 +   #+end_src
   2.239 +   #+end_listing
   2.240 +
   2.241 +   Actually running this simulation is easy given =CORTEX='s facilities.
   2.242 +
   2.243 +   #+caption: Collect experiences while the worm moves around. Filter the touch 
   2.244 +   #+caption: sensations by stable ones, collapse similiar ones together, 
   2.245 +   #+caption: and report the regions learned.
   2.246 +   #+name: learn-touch
   2.247 +   #+begin_listing clojure
   2.248 +   #+begin_src clojure
   2.249 +(defn learn-touch-regions []
   2.250 +  (let [experiences (atom [])
   2.251 +        world (apply-map
   2.252 +               worm-world
   2.253 +               (assoc (worm-segment-defaults)
   2.254 +                 :experiences experiences))]
   2.255 +    (run-world world)
   2.256 +    (->>
   2.257 +     @experiences
   2.258 +     (drop 175)
   2.259 +     ;; access the single segment's touch data
   2.260 +     (map (comp first :touch))
   2.261 +     ;; only deal with "pure" touch data to determine surfaces
   2.262 +     (filter pure-touch?)
   2.263 +     ;; associate coordinates with touch values
   2.264 +     (map (partial apply zipmap))
   2.265 +     ;; select those regions where contact is being made
   2.266 +     (map (partial group-by second))
   2.267 +     (map #(get % full-contact))
   2.268 +     (map (partial map first))
   2.269 +     ;; remove redundant/subset regions
   2.270 +     (map set)
   2.271 +     remove-similar)))
   2.272 +
   2.273 +(defn learn-and-view-touch-regions []
   2.274 +  (map view-touch-region
   2.275 +       (learn-touch-regions)))
   2.276 +   #+end_src
   2.277 +   #+end_listing
   2.278 +
   2.279 +   The only thing remining to define is the particular motion the worm
   2.280 +   must take. I accomplish this with a simple motor control program.
   2.281 +
   2.282 +   #+caption: Motor control program for making the worm roll on the ground.
   2.283 +   #+caption: This could also be replaced with random motion.
   2.284 +   #+name: worm-roll
   2.285 +   #+begin_listing clojure
   2.286 +   #+begin_src clojure
   2.287 +(defn touch-kinesthetics []
   2.288 +  [[170 :lift-1 40]
   2.289 +   [190 :lift-1 19]
   2.290 +   [206 :lift-1  0]
   2.291 +
   2.292 +   [400 :lift-2 40]
   2.293 +   [410 :lift-2  0]
   2.294 +
   2.295 +   [570 :lift-2 40]
   2.296 +   [590 :lift-2 21]
   2.297 +   [606 :lift-2  0]
   2.298 +
   2.299 +   [800 :lift-1 30]
   2.300 +   [809 :lift-1 0]
   2.301 +
   2.302 +   [900 :roll-2 40]
   2.303 +   [905 :roll-2 20]
   2.304 +   [910 :roll-2  0]
   2.305 +
   2.306 +   [1000 :roll-2 40]
   2.307 +   [1005 :roll-2 20]
   2.308 +   [1010 :roll-2  0]
   2.309 +   
   2.310 +   [1100 :roll-2 40]
   2.311 +   [1105 :roll-2 20]
   2.312 +   [1110 :roll-2  0]
   2.313 +   ])
   2.314 +   #+end_src
   2.315 +   #+end_listing
   2.316 +
   2.317 +
   2.318 +   #+caption: The small worm rolls around on the floor, driven
   2.319 +   #+caption: by the motor control program in listing \ref{worm-roll}.
   2.320 +   #+name: worm-roll
   2.321 +   #+ATTR_LaTeX: :width 12cm
   2.322 +   [[./images/worm-roll.png]]
   2.323 +
   2.324 +
   2.325 +   #+caption: After completing its adventures, the worm now knows 
   2.326 +   #+caption: how its touch sensors are arranged along its skin. These 
   2.327 +   #+caption: are the regions that were deemed important by 
   2.328 +   #+caption: =learn-touch-regions=. Note that the worm has discovered
   2.329 +   #+caption: that it has six sides.
   2.330 +   #+name: worm-touch-map
   2.331 +   #+ATTR_LaTeX: :width 12cm
   2.332 +   [[./images/touch-learn.png]]
   2.333 +
   2.334 +   While simple, =learn-touch-regions= exploits regularities in both
   2.335 +   the worm's physiology and the worm's environment to correctly
   2.336 +   deduce that the worm has six sides. Note that =learn-touch-regions=
   2.337 +   would work just as well even if the worm's touch sense data were
   2.338 +   completely scrambled. The cross shape is just for convienence. This
   2.339 +   example justifies the use of pre-defined touch regions in =EMPATH=.
   2.340 +
   2.341  * Contributions
   2.342  
   2.343  
     3.1 Binary file thesis/images/touch-learn.png has changed
     4.1 Binary file thesis/images/worm-roll.png has changed
     5.1 --- a/thesis/rlm-cortex-meng.tex	Wed Mar 26 20:38:17 2014 -0400
     5.2 +++ b/thesis/rlm-cortex-meng.tex	Wed Mar 26 22:17:42 2014 -0400
     5.3 @@ -45,6 +45,11 @@
     5.4  \usepackage{libertine}
     5.5  \usepackage{inconsolata}
     5.6  \usepackage{rotating}
     5.7 +\usepackage{caption}
     5.8 +
     5.9 +%\usepackage{afterpage}
    5.10 +
    5.11 +%\afterpage{\clearpage}          %
    5.12  
    5.13  \usepackage[backend=bibtex,style=alphabetic]{biblatex}
    5.14  \addbibresource{cortex.bib}
    5.15 @@ -58,6 +63,8 @@
    5.16      citecolor={dark-blue}, urlcolor={medium-blue}
    5.17  }
    5.18  
    5.19 +\newenvironment{code}{\captionsetup{type=listing}}{}
    5.20 +
    5.21  \renewcommand{\thesection}{\arabic{section}}
    5.22  \renewcommand{\thefigure}{\arabic{figure}}
    5.23  
    5.24 @@ -82,6 +89,27 @@
    5.25  %\usepackage{lgrind}
    5.26  \pagestyle{plain}
    5.27  
    5.28 +
    5.29 +%% % Alter some LaTeX defaults for better treatment of figures:
    5.30 +%% % See p.105 of "TeX Unbound" for suggested values.
    5.31 +%% % See pp. 199-200 of Lamport's "LaTeX" book for details.
    5.32 +%% %   General parameters, for ALL pages:
    5.33 +%% \renewcommand{\topfraction}{0.9}	% max fraction of floats at top
    5.34 +%% \renewcommand{\bottomfraction}{0.8}	% max fraction of floats at bottom
    5.35 +%% %   Parameters for TEXT pages (not float pages):
    5.36 +%% \setcounter{topnumber}{2}
    5.37 +%% \setcounter{bottomnumber}{2}
    5.38 +%% \setcounter{totalnumber}{4}     % 2 may work better
    5.39 +%% \setcounter{dbltopnumber}{2}    % for 2-column pages
    5.40 +%% \renewcommand{\dbltopfraction}{0.9}	% fit big float above 2-col. text
    5.41 +%% \renewcommand{\textfraction}{0.07}	% allow minimal text w. figs
    5.42 +%% %   Parameters for FLOAT pages (not text pages):
    5.43 +%% \renewcommand{\floatpagefraction}{0.7}	% require fuller float pages
    5.44 +%% % N.B.: floatpagefraction MUST be less than topfraction !!
    5.45 +%% \renewcommand{\dblfloatpagefraction}{0.7}	% require fuller float pages
    5.46 +%% % remember to use [htp] or [htpb] for placement
    5.47 +
    5.48 +
    5.49  \begin{document}
    5.50  
    5.51  \include{cover}