<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel rdf:about="https://community.wolfram.com">
    <title>Community RSS Feed</title>
    <link>https://community.wolfram.com</link>
    <description>RSS Feed for Wolfram Community showing ideas tagged with Artificial Intelligence sorted by most viewed.</description>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/995095" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1093926" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/3288988" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/884348" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/2108301" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1787163" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1207400" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1221098" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/480226" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1341081" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/970999" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1646303" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/465774" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1732399" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1016315" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1647625" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1379001" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1732586" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1383518" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/3394441" />
      </rdf:Seq>
    </items>
  </channel>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/995095">
    <title>How many animals can one find in a random image?</title>
    <link>https://community.wolfram.com/groups/-/m/t/995095</link>
    <description>![enter image description here][18]&#xD;
&#xD;
The long evolutionary history of humans has optimized the recognition of animals in the human vision system. To escape predators and to find food. Sometimes we believe to see animals and human faces, even if there aren&amp;#039;t any, this phenomena is called [pareidolia][1], or more generally apophenia. Classic examples are Jesus on a toast ([Liu2014][2]), the image on the shroud of Turin ([Sheen2016][3]), Elvis in a potato chip ([Voss2011][4]), and the face on Mars ([Martinez-Conde2012][5]).  In many cases, in about 100ms ([Naber2012][6]) humans can identify animal shapes. Some animals, e.g. snakes are potentially identified much faster ([VanLe2013][7]).&#xD;
&#xD;
So, an interesting question might be: how often do we (believe to) see animals in an genuinely random image?&#xD;
&#xD;
Here is, in the literal sense of the word, a random image of size 300*300 pixels:&#xD;
&#xD;
    SeedRandom[4056380]; &#xD;
    dim=300;&#xD;
    randomImage = Image[Table[RandomChoice[{2,1}-&amp;gt;{0,1}],{dim},{dim}]];&#xD;
    Show[randomImage,ImageSize -&amp;gt; 300]&#xD;
&#xD;
![enter image description here][8]&#xD;
&#xD;
No animal shapes are directly visible.&#xD;
&#xD;
Using ImageMesh we can get the individual/connected components (some potentially animal-like shaped) as regions (this operation is not fully deterministic, so results below may vary).&#xD;
&#xD;
    Show[imesh=ImageMesh[randomImage,Method-&amp;gt;&amp;#034;DualMarchingSquares&amp;#034;],ImageSize -&amp;gt; 300]&#xD;
&#xD;
![enter image description here][9]&#xD;
&#xD;
These are the individual shapes. We ignore too small and too large regions. For our image we find neatly 400 regions.&#xD;
&#xD;
    (* this takes a minute *)&#xD;
    shapes=Select[ConnectedMeshComponents@imesh,18&amp;lt; Area[#]&amp;lt;2000&amp;amp;];&#xD;
    Length[shapes]&#xD;
&#xD;
`393`&#xD;
&#xD;
These are the shapes positioned in the original image.&#xD;
&#xD;
    Show[HighlightMesh[#,Style[2, RandomColor[]]]&amp;amp;/@ shapes]&#xD;
&#xD;
![enter image description here][10]&#xD;
&#xD;
For later use, we define one function to make a random image and get the shapes.&#xD;
&#xD;
    getShapes[{black_,white_}, dim_] :=Select[ConnectedMeshComponents@&#xD;
    ImageMesh[Image[Table[RandomChoice[{black,white}-&amp;gt;{0,1}],{dim},{dim}]],&#xD;
    Method-&amp;gt;&amp;#034;DualMarchingSquares&amp;#034;],18&amp;lt; Area[#]&amp;lt;2000&amp;amp;]&#xD;
&#xD;
As we want to interpret the shapes as animals, we smooth the edges. We switch from regions to graphics.&#xD;
&#xD;
    smooth[reg_] :=Graphics[{Lighter[Blue], &#xD;
    (ToExpression[ToString[InputForm@reg],StandardForm,Hold] /.&#xD;
    HoldPattern[BoundaryMeshRegion[v_,b__,___Rule]]:&amp;gt;GraphicsComplex[v,FilledCurve[{b}/.&#xD;
    Line[l_]:&amp;gt; BSplineCurve[DeleteDuplicates[Flatten[l,1]],&#xD;
    SplineClosed-&amp;gt;True,SplineDegree-&amp;gt;2]]])[[1]]}]&#xD;
&#xD;
We also allow changing the orientation and color.&#xD;
&#xD;
    rotate[g_,?_] := With[{m={{Cos[?],Sin[?]},{-Sin[?], Cos[?]}}},g/.&#xD;
    GraphicsComplex[v_, r__]:&amp;gt; GraphicsComplex[m.#&amp;amp;/@ v,r]]&#xD;
    &#xD;
    flip[g_] := g/.GraphicsComplex[v_, r__]:&amp;gt; GraphicsComplex[{-1,1}#&amp;amp;/@ v,r]&#xD;
    &#xD;
    recolor[g_,col_] := g/.c_RGBColor:&amp;gt;col&#xD;
    &#xD;
    animalize[g_,{f_,?_,col_}] := Graphics[ recolor[rotate[If[f, flip,Identity]@&#xD;
    smooth[g],?],col], PlotRange -&amp;gt; All]&amp;amp;[smooth[g]]&#xD;
&#xD;
Here are some of the shapes that were hiding in the above image.The human eye tries to see fishes, wales, birds, squirrels, frogs, ducks, sea-horses, bunnies, deers, dogs, cats and similar creatures as well as human heads.&#xD;
&#xD;
    GraphicsGrid[Partition[Show[#, ImageSize -&amp;gt; 120,Frame-&amp;gt;True,FrameTicks-&amp;gt;False]&amp;amp;/@#,5]&amp;amp;@&#xD;
    { animalize[shapes[[18]],{False,1.8,GrayLevel[0.1]}],&#xD;
      animalize[shapes[[99]],{False,1.1,Darker[Yellow]}], &#xD;
      animalize[shapes[[6]],{False,0.7,Darker[Blue]}],&#xD;
      animalize[shapes[[14]],{False,0.,Darker[Brown]}],&#xD;
      animalize[shapes[[4]],{False,0.5,Darker[Red]}],&#xD;
      animalize[shapes[[23]],{False,0,Darker[Orange]}],&#xD;
      animalize[shapes[[76]],{False,0,Darker[Orange,0.6]}],&#xD;
      animalize[shapes[[95]],{False,-1.5,Darker[Green,0.4]}], &#xD;
      animalize[shapes[[9]],{False,0.,Brown}],&#xD;
      animalize[shapes[[163]],{False,1.1,Darker[Purple]}]},&#xD;
    Spacings-&amp;gt;{5,-20}]&#xD;
&#xD;
![enter image description here][11]&#xD;
&#xD;
Looking at the last selection shows the importance of one or two eyes in the shapes ([Yang2015][12]). Eyes are often used by nature for deception ([Steven2014][13]).&#xD;
&#xD;
A small Manipulate will allow to optimize the animal-perception by changing color, orientation, and aspect ratio.&#xD;
&#xD;
    makeManipulate[shape_]:=Manipulate[Graphics[ recolor[rotate[If[f, flip,Identity]@ #[[1]],?],col],&#xD;
    ImageSize -&amp;gt; 120,AspectRatio-&amp;gt;ar,PlotRange -&amp;gt; All],&#xD;
    OpenerView[{&amp;#034;modify&amp;#034;,Column[{&#xD;
    Control[{{?,0,&amp;#034;rotate&amp;#034;},-Pi,Pi,ImageSize-&amp;gt;Small}],&#xD;
    Control[{{f,False,&amp;#034;reflect&amp;#034;},{True,False},ImageSize-&amp;gt;Small}],&#xD;
    Control[{{col, Darker[Blue],&amp;#034;color&amp;#034;},Red,ImageSize-&amp;gt;Tiny}],&#xD;
    Control[{{ar, Automatic,&amp;#034;aspect ratio&amp;#034;},0.2,5,ImageSize-&amp;gt;Small}]}]}],&#xD;
    SaveDefinitions-&amp;gt;True,TrackedSymbols:&amp;gt;True]&amp;amp;[smooth[#]]&amp;amp;@ shape&#xD;
    &#xD;
    Manipulate[makeManipulate[shapes[[j]]],{{j,141,&amp;#034;&amp;#034;},1, Length[shapes],1,Appearance-&amp;gt;&amp;#034;Labeled&amp;#034;}]&#xD;
&#xD;
![enter image description here][14]&#xD;
&#xD;
Here are some more animal-shapes found in other random images. &#xD;
&#xD;
![enter image description here][15]&#xD;
&#xD;
One could now try to automate the finding of animals using ImageIdentify. In general, the interpretation of ImageIdentify will depend on the image orientation. So, we maximize over different orientations.&#xD;
&#xD;
    getOptimalAnimal[shape_] := &#xD;
    Module[{s=smooth[shape][[1]],tab,ras,tab2},&#xD;
    tab=Table[{(ras=Rasterize[Graphics[rotate[s,\[Alpha]],ImageSize -&amp;gt; 120,PlotRange -&amp;gt; All]]),&#xD;
          Normal@KeyDrop[ImageIdentify[ras,&amp;#034;animal&amp;#034;,2,&amp;#034;Probability&amp;#034;],Entity[&amp;#034;Concept&amp;#034;,#]&amp;amp;/@&#xD;
     {&amp;#034;Person::93r37&amp;#034;,&amp;#034;Hominid::tt93h&amp;#034;,&amp;#034;Mammal::nt5bz&amp;#034;,&#xD;
    &amp;#034;SeaStar::46w97&amp;#034;,&amp;#034;Shark::632s8&amp;#034;,&amp;#034;CanisFamiliaris::597qc&amp;#034;}]},&#xD;
    {\[Alpha], 0, 2Pi, 2Pi/24}]; &#xD;
    tab2=Sort[{#2[[1,2]], #2[[1,1]], #1}&amp;amp;@@@DeleteCases[ tab,{_,{}}]];&#xD;
    {tab2[[-1,3]]-&amp;gt;tab2[[-1,2]],&amp;#034;Probabilty&amp;#034; -&amp;gt; tab2[[-1,1]]}]&#xD;
&#xD;
As ImageIdentify was trained on real photographs, it is not the ideal tool for this task. It is biased towards humans, mammals, and sharks.&#xD;
&#xD;
    getOptimalAnimal[shapes[[10]]]&#xD;
&#xD;
![enter image description here][16]&#xD;
&#xD;
    getOptimalAnimal[shapes[[27]]]&#xD;
&#xD;
![enter image description here][17]&#xD;
&#xD;
To answer the original question: in a random 400x400 pixel image, one easily finds a few dozen animals. Here are four dozen animal-shape like smoothed regions from random 400x400 image.&#xD;
&#xD;
    Module[{gs, gs2},&#xD;
     SeedRandom[2222];&#xD;
     gs = getShapes[{2, 1}, 400];&#xD;
     gs2 = {animalize[gs[[3]], {False, 0, GrayLevel[0.1]}], &#xD;
       animalize[gs[[6]], {False, 1, GrayLevel[0.1]}], &#xD;
       animalize[gs[[9]], {False, 1.3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[15]], {False, -1, GrayLevel[0.1]}], &#xD;
       animalize[gs[[17]], {False, 0.3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[30]], {True, 2.3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[39]], {False, 0.3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[40]], {True, -0.1, GrayLevel[0.1]}], &#xD;
       animalize[gs[[48]], {False, -0.1, GrayLevel[0.1]}], &#xD;
       animalize[gs[[53]], {True, -0.1, GrayLevel[0.1]}], &#xD;
       animalize[gs[[55]], {True, -0.1, GrayLevel[0.1]}], &#xD;
       animalize[gs[[62]], {True, 2.3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[64]], {False, 0, GrayLevel[0.1]}], &#xD;
       animalize[gs[[65]], {False, 0, GrayLevel[0.1]}], &#xD;
       animalize[gs[[68]], {False, -0.2, GrayLevel[0.1]}], &#xD;
       animalize[gs[[73]], {True, -0.3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[81]], {False, 0.2, GrayLevel[0.1]}], &#xD;
       animalize[gs[[86]], {True, 3.4, GrayLevel[0.1]}], &#xD;
       animalize[gs[[97]], {False, 0.3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[100]], {False, 0.9, GrayLevel[0.1]}], &#xD;
       animalize[gs[[101]], {False, 2.6, GrayLevel[0.1]}], &#xD;
       animalize[gs[[115]], {False, 4.3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[124]], {False, 0, GrayLevel[0.1]}], &#xD;
       animalize[gs[[125]], {False, 2.9, GrayLevel[0.1]}], &#xD;
       animalize[gs[[139]], {False, 0, GrayLevel[0.1]}], &#xD;
       animalize[gs[[146]], {False, -1.6, GrayLevel[0.1]}], &#xD;
       animalize[gs[[175]], {False, -1., GrayLevel[0.1]}], &#xD;
       animalize[gs[[201]], {True, -0.5, GrayLevel[0.1]}], &#xD;
       animalize[gs[[209]], {True, 3.1, GrayLevel[0.1]}], &#xD;
       animalize[gs[[210]], {False, -1.4, GrayLevel[0.1]}], &#xD;
       animalize[gs[[218]], {True, 3.2, GrayLevel[0.1]}], &#xD;
       animalize[gs[[227]], {True, -0.3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[229]], {True, 0.9, GrayLevel[0.1]}], &#xD;
       animalize[gs[[253]], {True, 0., GrayLevel[0.1]}], &#xD;
       animalize[gs[[273]], {True, -0.3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[278]], {True, 1., GrayLevel[0.1]}], &#xD;
       animalize[gs[[282]], {True, 3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[298]], {False, 0, GrayLevel[0.1]}], &#xD;
       animalize[gs[[299]], {False, 0.6, GrayLevel[0.1]}], &#xD;
       animalize[gs[[318]], {False, 2., GrayLevel[0.1]}], &#xD;
       animalize[gs[[326]], {False, 3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[340]], {False, -1.3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[352]], {True, -13, GrayLevel[0.1]}], &#xD;
       animalize[gs[[361]], {True, -13, GrayLevel[0.1]}], &#xD;
       animalize[gs[[365]], {False, 2.4, GrayLevel[0.1]}], &#xD;
       animalize[gs[[377]], {True, 2.6, GrayLevel[0.1]}], &#xD;
       animalize[gs[[395]], {False, 0.3, GrayLevel[0.1]}], &#xD;
       animalize[gs[[405]], {True, 0.3, GrayLevel[0.1]}]};&#xD;
     Grid[Partition[Framed[Show[#, ImageSize -&amp;gt; 100]] &amp;amp; /@ &#xD;
        SortBy[gs2, FullOptions[#, AspectRatio] &amp;amp;], 6]]]&#xD;
&#xD;
![enter image description here][18]&#xD;
&#xD;
Using different method options for ImageMesh gives different results. Here are some animal-shaped regions from a 300*300 image and method &amp;#034;MarchingSquares&amp;#034;.&#xD;
&#xD;
![enter image description here][19]&#xD;
&#xD;
&#xD;
  [1]: https://en.wikipedia.org/wiki/Pareidolia&#xD;
  [2]: https://dx.doi.org/10.1016/j.cortex.2014.01.013&#xD;
  [3]: https://doi.org/10.1163/15736121-12341320&#xD;
  [4]: http://dx.doi.org/10.1093/cercor/bhr315&#xD;
  [5]: https://www.scientificamerican.com/article/a-faithful-resemblance/&#xD;
  [6]: http://dx.doi.org/10.1167/12.1.25&#xD;
  [7]: http://dx.doi.org/10.1073/pnas.1312648110&#xD;
  [8]: http://community.wolfram.com//c/portal/getImageAttachment?filename=4356yretet465yhdfreg5w4ytrg.png&amp;amp;userId=11733&#xD;
  [9]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fdfgnsgt65whtr.png&amp;amp;userId=11733&#xD;
  [10]: http://community.wolfram.com//c/portal/getImageAttachment?filename=dfgdhcvbcbcx34tq.png&amp;amp;userId=11733&#xD;
  [11]: http://community.wolfram.com//c/portal/getImageAttachment?filename=dfg4dsgdfsgdqy546hfgsnbv.png&amp;amp;userId=11733&#xD;
  [12]: http://arxiv.org/pdf/1509.04954&#xD;
  [13]: http://dx.doi.org/10.1093/czoolo/60.1.26&#xD;
  [14]: http://community.wolfram.com//c/portal/getImageAttachment?filename=weretregdfdgdscbx3454y6rtdfgsb.png&amp;amp;userId=11733&#xD;
  [15]: http://community.wolfram.com//c/portal/getImageAttachment?filename=sadfert543wyhdfgdhfd5676e565w44.png&amp;amp;userId=11733&#xD;
  [16]: http://community.wolfram.com//c/portal/getImageAttachment?filename=67567etfhg54yw.png&amp;amp;userId=11733&#xD;
  [17]: http://community.wolfram.com//c/portal/getImageAttachment?filename=sadf345q4yrthgd.png&amp;amp;userId=11733&#xD;
  [18]: http://community.wolfram.com//c/portal/getImageAttachment?filename=kfkeighsmf534yrthgfds.png&amp;amp;userId=11733&#xD;
  [19]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fdsg65udfsdstrdgjyt7u56uw56rh.png&amp;amp;userId=11733</description>
    <dc:creator>Michael Trott</dc:creator>
    <dc:date>2017-01-15T10:54:26Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1093926">
    <title>Transfer an artistic style to an image</title>
    <link>https://community.wolfram.com/groups/-/m/t/1093926</link>
    <description>![enter image description here][16]&#xD;
&#xD;
# Introduction &#xD;
&#xD;
Back in [Wolfram Summer School 2016][1] I worked on the project &amp;#034;Image Transformation with Neural Networks: Real-Time Style Transfer and Super-Resolution&amp;#034;, which got later [published on Wolfram Community][2]. At the time I had to use the MXNetLink package, but now all the needed functionality is built-in, so here is a top-level implementation of artistic style transfer with Wolfram Language. This is a slightly simplified version of the original method, as it uses a single VGG layer to extract the style features, but a full implementation is of course possible with minor modifications to the code. You can also find this example in the docs: &#xD;
&#xD;
[NetTrain][3] &amp;gt;&amp;gt; Applications &amp;gt;&amp;gt; Computer Vision &amp;gt;&amp;gt; Style Transfer &#xD;
&#xD;
# Code&#xD;
&#xD;
Create a new image with the content of a given image and in the style of another given image. This implementation follows the method described in Gatys et al., *A Neural Algorithm of Artistic Style*. An example content and style image:&#xD;
&#xD;
![enter image description here][4]&#xD;
&#xD;
To create the image which is a mix of both of these images, start by obtaining a pre-trained image classification network:&#xD;
&#xD;
    vggNet = NetModel[&amp;#034;VGG-16 Trained on ImageNet Competition Data&amp;#034;];&#xD;
Take a subnet that will be used as a feature extractor for the style and content images:&#xD;
&#xD;
    featureNet = Take[vggNet, {1, &amp;#034;relu4_1&amp;#034;}]&#xD;
![enter image description here][5]&#xD;
&#xD;
There are three loss functions used. The first loss ensures that the &amp;#034;content&amp;#034; is similar in the synthesized image and the content image:&#xD;
&#xD;
    contentLoss = NetGraph[{MeanSquaredLossLayer[]}, {1 -&amp;gt; NetPort[&amp;#034;LossContent&amp;#034;]}]&#xD;
![enter image description here][6]&#xD;
&#xD;
The second loss ensures that the &amp;#034;style&amp;#034; is similar in the synthesized image and the style image. Style similarity is defined as the mean-squared difference between the Gram matrices of the input and target:&#xD;
&#xD;
    gramMatrix = NetGraph[{FlattenLayer[-1], TransposeLayer[1 -&amp;gt; 2],   DotLayer[]}, {1 -&amp;gt; 3, 1 -&amp;gt; 2 -&amp;gt; 3}];&#xD;
&#xD;
    styleLoss = NetGraph[{gramMatrix, gramMatrix, MeanSquaredLossLayer[]},&#xD;
    {NetPort[&amp;#034;Input&amp;#034;] -&amp;gt; 1, NetPort[&amp;#034;Target&amp;#034;] -&amp;gt; 2, {1, 2} -&amp;gt; 3,  3 -&amp;gt; NetPort[&amp;#034;LossStyle&amp;#034;]}]&#xD;
![enter image description here][7]&#xD;
&#xD;
The third loss ensures that the magnitude of intensity changes across adjacent pixels in the synthesized image is small. This helps the synthesized image look more natural:&#xD;
&#xD;
    l2Loss = NetGraph[{ThreadingLayer[(#1 - #2)^2 &amp;amp;], SummationLayer[]}, {{NetPort[&amp;#034;Input&amp;#034;], NetPort[&amp;#034;Target&amp;#034;]} -&amp;gt; 1 -&amp;gt; 2}];&#xD;
&#xD;
    tvLoss = NetGraph[&amp;lt;|&#xD;
       &amp;#034;dx1&amp;#034; -&amp;gt; PaddingLayer[{{0, 0}, {1, 0}, {0, 0}}, &amp;#034;Padding&amp;#034; -&amp;gt; &amp;#034;Fixed&amp;#034; ],&#xD;
       &amp;#034;dx2&amp;#034; -&amp;gt;  PaddingLayer[{{0, 0}, {0, 1}, {0, 0}}, &amp;#034;Padding&amp;#034; -&amp;gt; &amp;#034;Fixed&amp;#034;],&#xD;
       &amp;#034;dy1&amp;#034; -&amp;gt;  PaddingLayer[{{0, 0}, {0, 0}, {1, 0}}, &amp;#034;Padding&amp;#034; -&amp;gt; &amp;#034;Fixed&amp;#034; ],&#xD;
       &amp;#034;dy2&amp;#034; -&amp;gt;  PaddingLayer[{{0, 0}, {0, 0}, {0, 1}}, &amp;#034;Padding&amp;#034; -&amp;gt; &amp;#034;Fixed&amp;#034;],&#xD;
       &amp;#034;lossx&amp;#034; -&amp;gt; l2Loss, &amp;#034;lossy&amp;#034; -&amp;gt; l2Loss, &amp;#034;tot&amp;#034; -&amp;gt; TotalLayer[]|&amp;gt;,&#xD;
     {{&amp;#034;dx1&amp;#034;, &amp;#034;dx2&amp;#034;} -&amp;gt; &amp;#034;lossx&amp;#034;, {&amp;#034;dy1&amp;#034;, &amp;#034;dy2&amp;#034;} -&amp;gt; &amp;#034;lossy&amp;#034;,&#xD;
       {&amp;#034;lossx&amp;#034;, &amp;#034;lossy&amp;#034;} -&amp;gt; &amp;#034;tot&amp;#034; -&amp;gt; NetPort[&amp;#034;LossTV&amp;#034;]}]&#xD;
![enter image description here][8]&#xD;
&#xD;
Define a function that creates the final training net for any content and style image. This function also creates a random initial image:&#xD;
&#xD;
    createTransferNet[net_, content_Image, styleFeatSize_] := Module[{dims = Prepend[3]@Reverse@ImageDimensions[content]},&#xD;
    NetGraph[&amp;lt;|&#xD;
    &amp;#034;Image&amp;#034; -&amp;gt; ConstantArrayLayer[&amp;#034;Array&amp;#034; -&amp;gt; RandomReal[{-0.1, 0.1}, dims]],&#xD;
    &amp;#034;imageFeat&amp;#034; -&amp;gt; NetReplacePart[net, &amp;#034;Input&amp;#034; -&amp;gt; dims],&#xD;
    &amp;#034;content&amp;#034; -&amp;gt; contentLoss,&#xD;
    &amp;#034;style&amp;#034; -&amp;gt; styleLoss,&#xD;
    &amp;#034;tv&amp;#034; -&amp;gt; tvLoss|&amp;gt;,&#xD;
    {&amp;#034;Image&amp;#034; -&amp;gt; &amp;#034;imageFeat&amp;#034;,&#xD;
    {&amp;#034;imageFeat&amp;#034;, NetPort[&amp;#034;ContentFeature&amp;#034;]} -&amp;gt; &amp;#034;content&amp;#034;,&#xD;
    {&amp;#034;imageFeat&amp;#034;, NetPort[&amp;#034;StyleFeature&amp;#034;]} -&amp;gt; &amp;#034;style&amp;#034;,&#xD;
    &amp;#034;Image&amp;#034; -&amp;gt; &amp;#034;tv&amp;#034;},&#xD;
    &amp;#034;StyleFeature&amp;#034; -&amp;gt; styleFeatSize   ] ]&#xD;
Define a [NetDecoder][9] for visualizing the predicted image:&#xD;
&#xD;
    meanIm = NetExtract[featureNet, &amp;#034;Input&amp;#034;][[&amp;#034;MeanImage&amp;#034;]]&#xD;
&#xD;
&amp;gt; {0.48502, 0.457957, 0.407604}&#xD;
&#xD;
    decoder = NetDecoder[{&amp;#034;Image&amp;#034;, &amp;#034;MeanImage&amp;#034; -&amp;gt; meanIm}]&#xD;
![enter image description here][10]&#xD;
&#xD;
The training data consists of features extracted from the content and style images. Define a feature extraction function:&#xD;
&#xD;
    extractFeatures[img_] := NetReplacePart[featureNet, &amp;#034;Input&amp;#034; -&amp;gt;NetEncoder[{&amp;#034;Image&amp;#034;, ImageDimensions[img], &#xD;
     &amp;#034;MeanImage&amp;#034; -&amp;gt;meanIm}]][img];&#xD;
&#xD;
Create a training set consisting of a single example of a content and style feature:&#xD;
&#xD;
    trainingdata = &amp;lt;|&#xD;
      &amp;#034;ContentFeature&amp;#034; -&amp;gt; {extractFeatures[contentImg]},&#xD;
       &amp;#034;StyleFeature&amp;#034; -&amp;gt; {extractFeatures[styleImg]}&#xD;
      |&amp;gt;&#xD;
Create the training net whose input dimensions correspond to the content and style image dimensions:&#xD;
&#xD;
    net = createTransferNet[featureNet, contentImg, &#xD;
       Dimensions@First@trainingdata[&amp;#034;StyleFeature&amp;#034;]];&#xD;
When training, the three losses are weighted differently to set the relative importance of the content and style. These values might need to be changed with different content and style images. Create a loss specification that defines the final loss as a combination of the three losses:&#xD;
&#xD;
    perPixel = 1/(3*Apply[Times, ImageDimensions[contentImg]]);&#xD;
    lossSpec = {&amp;#034;LossContent&amp;#034; -&amp;gt; Scaled[6.*10^-5], &#xD;
       &amp;#034;LossStyle&amp;#034; -&amp;gt; Scaled[0.5*10^-14], &#xD;
       &amp;#034;LossTV&amp;#034; -&amp;gt; Scaled[20.*perPixel]};&#xD;
Optimize the image using [NetTrain][11]. [LearningRateMultipliers][12] are used to freeze all parameters in the net except for the [ConstantArrayLayer][13]. The training is best done on a GPU, as it will take up to an hour to get good results with CPU training. The training can be stopped at any time via Evaluation -&amp;gt; Abort Evaluation:&#xD;
&#xD;
    trainedNet = NetTrain[net,&#xD;
      trainingdata, lossSpec,&#xD;
      LearningRateMultipliers -&amp;gt; {&amp;#034;Image&amp;#034; -&amp;gt; 1, _ -&amp;gt; None},&#xD;
      TrainingProgressReporting -&amp;gt; &#xD;
       Function[decoder[#Weights[{&amp;#034;Image&amp;#034;, &amp;#034;Array&amp;#034;}]]],&#xD;
      MaxTrainingRounds -&amp;gt; 300, BatchSize -&amp;gt; 1,&#xD;
      Method -&amp;gt; {&amp;#034;ADAM&amp;#034;, &amp;#034;InitialLearningRate&amp;#034; -&amp;gt; 0.05},&#xD;
      TargetDevice -&amp;gt; &amp;#034;GPU&amp;#034;&#xD;
      ]&#xD;
![enter image description here][14]&#xD;
&#xD;
Extract the final image from the [ConstantArrayLayer][15] of the trained net:&#xD;
&#xD;
    decoder[NetExtract[trainedNet, {&amp;#034;Image&amp;#034;, &amp;#034;Array&amp;#034;}]]&#xD;
&#xD;
![enter image description here][16]&#xD;
&#xD;
&#xD;
  [1]: https://education.wolfram.com/summer/school/alumni/2016/salvarezza/&#xD;
  [2]: http://community.wolfram.com/groups/-/m/t/885941&#xD;
  [3]: http://reference.wolfram.com/language/ref/NetTrain.html&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=I_432.png&amp;amp;userId=95400&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=O_179.png&amp;amp;userId=95400&#xD;
  [6]: http://community.wolfram.com//c/portal/getImageAttachment?filename=O_180.png&amp;amp;userId=95400&#xD;
  [7]: http://community.wolfram.com//c/portal/getImageAttachment?filename=O_181.png&amp;amp;userId=95400&#xD;
  [8]: http://community.wolfram.com//c/portal/getImageAttachment?filename=O_182.png&amp;amp;userId=95400&#xD;
  [9]: http://reference.wolfram.com/language/ref/NetDecoder.html&#xD;
  [10]: http://community.wolfram.com//c/portal/getImageAttachment?filename=O_184.png&amp;amp;userId=95400&#xD;
  [11]: http://reference.wolfram.com/language/ref/NetTrain.html&#xD;
  [12]: http://reference.wolfram.com/language/ref/LearningRateMultipliers.html&#xD;
  [13]: http://reference.wolfram.com/language/ref/ConstantArrayLayer.html&#xD;
  [14]: http://community.wolfram.com//c/portal/getImageAttachment?filename=O_185.png&amp;amp;userId=95400&#xD;
  [15]: http://reference.wolfram.com/language/ref/ConstantArrayLayer.html&#xD;
  [16]: http://community.wolfram.com//c/portal/getImageAttachment?filename=I_466.png&amp;amp;userId=95400</description>
    <dc:creator>Matteo Salvarezza</dc:creator>
    <dc:date>2017-05-15T10:33:59Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/3288988">
    <title>Empowering mathematics education through programming with Wolfram AI and chat-enabled notebooks</title>
    <link>https://community.wolfram.com/groups/-/m/t/3288988</link>
    <description>&amp;amp;[Wolfram Notebook][1]&#xD;
&#xD;
&#xD;
  [1]: https://www.wolframcloud.com/obj/390b3f6c-6c28-477b-9f08-d74f7f24ea7d</description>
    <dc:creator>Paul Abbott</dc:creator>
    <dc:date>2024-10-01T17:36:50Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/884348">
    <title>[WSS16] Image Colorization</title>
    <link>https://community.wolfram.com/groups/-/m/t/884348</link>
    <description>The aim of my project for the Wolfram Science Summer School was to build a neural network which could be able to colorize grayscale images in a realistic way. The network has been built following the article [1]. In this paper, the authors propose a fully automated approach for colorization of grayscale images, which uses a combination of global image features, which are extracted from the entire image, and local image features, which are computed from small image patches. Global priors provide information at an image level such as whether or not the image was taken indoors or outdoors, whether it is day or night, etc., while local features represent the local texture or object at a given location. By combining both features, it&amp;#039;s possible to leverage the semantic information to color the images without requiring human interaction. The approach is based on Convolutional Neural Networks, which have a strong capacity for learning and is trained to predict the chrominance of a grayscale image using the CIE L*a*b* colorspace. Predicting colors has the nice property that training data is practically free: any color photo can be used as a training example. &#xD;
&#xD;
**Net Layers**&#xD;
&#xD;
The model consists of four main components: a low-level features network, a mid-level features network, a global features network, and a colorization network. First, a common set of shared low-level features are extracted from the image. Using these features, a set of global image features and mid-level image features are computed. Then, the mid-level and the global features are both fused by a &amp;#034;fusion layer&amp;#034; and used as the input to a colorization network that outputs the final chrominance map. &#xD;
Each layer has a ReLu transfer function except for the last convolution of the colorization network, where a sigmoid function is applied.The model is able to process images of any size, but it is most efficient when the input images are 224x224 pixels, as the shared low-level features layers can share outputs. Note that when the input image size is of a different resolution, while the low-level feature weights are shared, a rescaled image of size 224x224 must be used for the global features network.This requires processing both the original image and the rescaled image through the low-level features network, increasing both memory consumption and computation time. For this reason, we trained&#xD;
the model exclusively with images of size 224x224 pixels.&#xD;
&#xD;
*Low-Level Features Network*&#xD;
&#xD;
A 6-layer Convolutional Neural Network obtains low-level features directly from the input image. The convolution filter bank the network represents are shared to feed both the global features network and the mid-level features network. In order to reduce the size of the feature maps, we use convolution layers with increased strides instead of using max-pooling layers (as usual for similar kinds of networks). If padding is added to the layer, the output is effectively half the size of the input layer. We used 3x3 convolution kernels exclusively and a padding of 1x1 to ensure the output is the same size (or half if using a stride of 2) as the input.&#xD;
&#xD;
*Global Features Network*&#xD;
&#xD;
The global image features are obtained by further processing the low-level features with four convolutional layers followed by three fully-connected layers.This results in a 256-dimensional vector representation of the image.&#xD;
&#xD;
*Mid-Level Features Network*&#xD;
&#xD;
The mid-level features are obtained by processing the low-level features further with two convolutional layers. The output is bottlenecked from the original 512-channel low-level features to 256-channel mid-level features. Unlike the global image features, the low-level and mid-level features networks are fully convolutional networks, such that the output is a scaled version of the input.&#xD;
&#xD;
*Fusion Layer*&#xD;
&#xD;
In order to be able to combine the global image features, a 256-dimensional vector, with the (mid-level) local image features, a 28x28x256-dimensional tensor, the authors introduce a fusion layer. This can be thought of as concatenating the global features with the local features at each spatial location and processing them through a small one-layer network.This effectively combines the global feature and the local features to obtain a new feature map that is, as the mid-level features, a 3D volume.&#xD;
&#xD;
*Colorization Network*&#xD;
&#xD;
Once the features are fused, they are processed by a set of convolutions and upsampling layers, which use the nearest neighbour technique so that the output is twice as wide and twice as tall. These layers are alternated until the output is half the size of the original input. The&#xD;
output layer of the colorization network consists of a convolutional layer with a Sigmoid transfer function that outputs the chrominance of the input grayscale image. Finally, the computed chrominance is upsampled and combined with the input intensity/luminance image to produce the resulting color image. In order to train the network, we used the Mean Square Error (MSE) criterion. Given a color image for training, the input of the model is the grayscale image while the target output is the a*b* components of the CIE L*a*b* colorspace. The a*b* components are globally normalized so they lie in the [0,1] range of the Sigmoid transfer function. &#xD;
&#xD;
*Colorization with Classification*&#xD;
&#xD;
While training with only color images using the MSE criterion does give good performance, sometimes it could make obvious mistakes due to not properly learning the global context of the image, e.g., whether it is indoors or outdoors. As learning these networks is an non-convex&#xD;
problem, we facilitated the optimization by also training for classification jointly with the colorization. As we trained the model using a large-scale dataset for classification of N classes (Mathematica ImageIdentify dataset), we had classification labels available for training. These labels correspond to a global image tag and thus can be used to guide the training of the global image features. We did this by introducing another very small neural network that consists of two fully-connected layers: a hidden layer with 256 outputs and an output layer with as many outputs as the number of classes in the dataset. The input of this network is the second to last layer of the global features network with 512 outputs. We trained this network using the cross-entropy loss, jointly with the MSE loss for the colorization network.&#xD;
&#xD;
*Implementation*&#xD;
&#xD;
The aim of my project was to build the network described in the paper using the new NeuralNetworks framework of Mathematica 11. In order to achieve this, some adjustments were needed. &#xD;
First of all, we decided to train and evaluate the network only on images of 224x224 pixels size, in order to use (and train) only one low-level features network, instead of two with shared weights and different outputs.&#xD;
The final network has two inputs: the first one is the colored 224x224 px image, encoded by the &amp;#034;NetEncoder&amp;#034; function in LAB colorspace, the second one the class of the image. The two outputs (named &amp;#034;Loss&amp;#034; and &amp;#034;Output&amp;#034;) represent the values of the two loss function used (one for the colorization, the other one for the classification), which are then summed together by the NetTrain function. The three color channels of the input image are split by the split layer: the L channel feeds the &amp;#034;low-level features&amp;#034; network, while the a,b channels are scaled and concatenated in order to obtain a target set for the mean squared loss function comparable with the output of the colorization network. The fusion layer has been replaced by a broadcast layer, which joins the rank 3- tensor, output of the mid-level network, with the vector from the global features network. However, the way they are combined is not exactly the same as the one described in the paper. To evaluate the trained network on a grayscale image it&amp;#039;s necessary to drop some branches of the network, such as the classification network and the layers that process the a,b channels of the colored input image in order to produce the target set for the colorization loss function. &#xD;
&#xD;
![Network described in the paper][1]&#xD;
![Network implementation with Mathematica NeuralNetworks framework][2]&#xD;
&#xD;
**Results**&#xD;
&#xD;
![enter image description here][3]&#xD;
&#xD;
**Conclusions**&#xD;
&#xD;
The network described in the paper has been trained on the Places scene dataset [Zhou et al. 2014], which consists of 2,448,872 training images and 20,500 validation images, with 205 classes corresponding to the types of the scene. They filtered the images by removing grayscale images and those that have little color variance with a small automated script. They trained using a batch size of 128 for 200,000 iterations corresponding to roughly 11 epochs. This takes roughly 3 weeks on one core of a NVIDIAR TeslaR K80 GPU. &#xD;
We needed to introduce some new layers in the existing framework and to fix some bugs, so we were able to train our network only for 14 hours on a dataset of 350000 images on one core of a GPU Titan machine. Furthermore, the images in our training set mainly represent specific items, so probably better results may be achieved introducing also images of different types of subjects (landscapes, human created images, indoors, etc). The results we obtained are showed in the section above and are quite good. We are confident that with a deeper and longer training our network would give considerably better results.&#xD;
&#xD;
**Open Problems / Future Developments**&#xD;
&#xD;
Due to the separation between the global and local features, it is possible to use global features computed on one image in combination with local features computed on another image, to change the style of the resulting colorization. One of the more interesting things the model can do is adapting the colorization of one image to the style of another. This is straight-forward to do with this model due to the decorrelation between the global features and the mid-level features. In order to colorize an image A using the style taken from an image B, it&amp;#039;s necessary to compute the mid-level local features of image A and the global features from image B. Than it&amp;#039;s possible to fuse these features and process them with the colorization network. Both the local and the global features are computed from grayscale images: it&amp;#039;s not necessary to use any color&#xD;
information at all.&#xD;
&#xD;
The main limitation of the method lies in the fact that it is datadriven and thus will only be able to colorize images that share common properties with those in the training set. In order to evaluate on significantly different types of images, it would be necessary to train a&#xD;
the model for all type of images (indoor, outdoor, human-created...). In order to obtain good style transfer results, it is important for both images to have some semantic level of similarity between them.&#xD;
&#xD;
**References**&#xD;
&#xD;
[1] Satoshi Iizuka, Edgar Simo - Serra, and Hiroshi Ishikawa.&amp;#034;Let there be Color!: Joint End-to-end Learning of Global and Local Image Priors for Automatic Image Colorization with Simultaneous Classification&amp;#034;.&#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=netwPicture.png&amp;amp;userId=884315&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=MyNetwork.png&amp;amp;userId=884315&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=result2.png&amp;amp;userId=884315</description>
    <dc:creator>Sabrina Giollo</dc:creator>
    <dc:date>2016-07-07T19:53:19Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/2108301">
    <title>MusicalScaleSample: Recognition and Methods</title>
    <link>https://community.wolfram.com/groups/-/m/t/2108301</link>
    <description># Purpose and Methods:&#xD;
&#xD;
*Some time ago I published on the WFR (Wolfram Function Repository) the function [MusicalScaleSample][1], where a sound scale sample can be generated. Which can be 30 different scales possible with this WFR item. But how to know which scale was the origin that generated the samples themselves? This is what this work is about, where I approach some methods, from semi-mechanics to machine learning with the comment on the results afterwards.*&#xD;
&#xD;
The methods covered here have this order below (of course, there are many other methods, here some in a briefly addressed way and others more detailed):&#xD;
&#xD;
- Semi-mechanical / Pitch Frequency&#xD;
&#xD;
- Pitch Sound Note&#xD;
&#xD;
- Classify / Method Neural Net&#xD;
&#xD;
- Classify / Method Naive Bayes&#xD;
&#xD;
- Customized ResNet&#xD;
&#xD;
These methods are (more or less) in the order of machine complexity x efficiency, the latter, Customized ResNet, was the method that generated the best results (as we going to see). In the course of this work I will comment on each method, it´s limitations and results.&#xD;
&#xD;
# Initial Samples / Sound:&#xD;
&#xD;
The musical scales follow patterns that can be represented by the distances between your notes, so, as a first step, we have these distances below:&#xD;
&#xD;
    sequences = {&amp;#034;MajorPentatonic&amp;#034; -&amp;gt; {0, 2, 2, 3, 2}, &#xD;
       &amp;#034;MinorPentatonic&amp;#034; -&amp;gt; {0, 3, 2, 2, 3}, &#xD;
       &amp;#034;NeopolitanMajor&amp;#034; -&amp;gt; {0, 1, 2, 2, 2, 2, 2}, &#xD;
       &amp;#034;NeopolitanMinor&amp;#034; -&amp;gt; {0, 1, 2, 2, 2, 1, 3}, &#xD;
       &amp;#034;HungarianMajor&amp;#034; -&amp;gt; {0, 3, 1, 2, 1, 2, 1}, &#xD;
       &amp;#034;HungarianMinor&amp;#034; -&amp;gt; {0, 2, 1, 3, 1, 1, 3}, &#xD;
       &amp;#034;HungarianGypsy&amp;#034; -&amp;gt; {0, 2, 2, 2, 1, 1, 2}, &#xD;
       &amp;#034;HarmonicMajor&amp;#034; -&amp;gt; {0, 2, 2, 1, 2, 1, 3}, &#xD;
       &amp;#034;HarmonicMinor&amp;#034; -&amp;gt; {0, 2, 1, 2, 2, 1, 3}, &#xD;
       &amp;#034;DoubleHarmonic&amp;#034; -&amp;gt; {0, 1, 3, 1, 2, 1, 3}, &#xD;
       &amp;#034;JazzMinor&amp;#034; -&amp;gt; {0, 2, 1, 2, 2, 2, 2}, &#xD;
       &amp;#034;Overtone&amp;#034; -&amp;gt; {0, 2, 2, 2, 1, 2, 1}, &#xD;
       &amp;#034;BluesScale&amp;#034; -&amp;gt; {0, 3, 2, 1, 1, 3}, &#xD;
       &amp;#034;Chromatic&amp;#034; -&amp;gt; {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, &#xD;
       &amp;#034;WholeTone&amp;#034; -&amp;gt; {0, 2, 2, 2, 2, 2}, &#xD;
       &amp;#034;DiminishedWholeTone&amp;#034; -&amp;gt; {0, 1, 2, 1, 2, 2, 2}, &#xD;
       &amp;#034;Symmetrical&amp;#034; -&amp;gt; {0, 1, 2, 1, 2, 1, 2, 1}, &#xD;
       &amp;#034;Arabian&amp;#034; -&amp;gt; {0, 2, 2, 1, 1, 2, 2}, &amp;#034;Balinese&amp;#034; -&amp;gt; {0, 1, 2, 4, 1}, &#xD;
       &amp;#034;Byzantine&amp;#034; -&amp;gt; {0, 1, 3, 1, 2, 1, 3}, &#xD;
       &amp;#034;Persian&amp;#034; -&amp;gt; {0, 1, 3, 1, 1, 2, 3}, &#xD;
       &amp;#034;EastIndianPurvi&amp;#034; -&amp;gt; {0, 1, 3, 2, 1, 1, 3}, &#xD;
       &amp;#034;Oriental&amp;#034; -&amp;gt; {0, 1, 3, 1, 1, 3, 1}, &#xD;
       &amp;#034;GagakuRyoSenPou&amp;#034; -&amp;gt; {0, 2, 2, 3, 2}, &#xD;
       &amp;#034;Zokugaku&amp;#034; -&amp;gt; {0, 3, 2, 2, 3}, &amp;#034;InSenPou&amp;#034; -&amp;gt; {0, 1, 4, 2, 1}, &#xD;
       &amp;#034;Okinawa&amp;#034; -&amp;gt; {0, 4, 1, 2, 4}, &amp;#034;Enigmatic&amp;#034; -&amp;gt; {0, 1, 3, 2, 2, 2, 1},&#xD;
        &amp;#034;EightToneSpanish&amp;#034; -&amp;gt; {0, 1, 2, 1, 1, 1, 2, 2}, &#xD;
       &amp;#034;Prometheus&amp;#034; -&amp;gt; {0, 2, 2, 2, 3, 1}};&#xD;
&#xD;
Below, is a sample of a scale, in this case &amp;#034;Enigmatic&amp;#034;, as well as its signature through the PitchRecognize command represented in a ListLinePlot chart. It is worth noting that the duration of each note is relatively short, so that the peaks of the notes do not extend like a hill, but rather more defined peaks so that there are better chances of being recognized:&#xD;
&#xD;
    Sound@Table[&#xD;
      ResourceFunction[&amp;#034;MusicalScaleSample&amp;#034;][&amp;#034;Enigmatic&amp;#034;, &amp;#034;Tone&amp;#034; -&amp;gt; &amp;#034;C3&amp;#034;, &#xD;
       &amp;#034;NoteInterval&amp;#034; -&amp;gt; 0.15, &amp;#034;Playing&amp;#034; -&amp;gt; &amp;#034;Mechanical&amp;#034;], 5]&#xD;
    ListLinePlot[PitchRecognize[%], &#xD;
     ColorFunction -&amp;gt; Function[{x, y}, Hue[y]], PlotStyle -&amp;gt; Thin, &#xD;
     AxesStyle -&amp;gt; Directive[Black, 12]]&#xD;
&#xD;
![im1][2]&#xD;
&#xD;
# Semi-mechanical / Pitch Frequency&#xD;
&#xD;
First, a function is developed that generates the musical note through PitchRecognize/Frequency; the equation itself is mechanical, although the recognition command already has characteristics of neural networks associated:&#xD;
&#xD;
    notes[x_] := &#xD;
     Keys@Counts[&#xD;
       Round[-36 + (12 Log[1/55 2^(3/4) #])/Log[2]] &amp;amp; /@ &#xD;
        QuantityMagnitude@&#xD;
         DeleteMissing@Values@PitchRecognize[x, &amp;#034;Frequency&amp;#034;]]&#xD;
&#xD;
Below is the conversion of the intervals of the notes in the notes themselves (taking into account 7 different octaves):&#xD;
&#xD;
    numb = Table[-48 + # &amp;amp; /@ &#xD;
         Flatten[# + Accumulate[Values@sequences[[x]]] &amp;amp; /@ {0, 12, 24, &#xD;
            36, 48, 60, 72}] -&amp;gt; Keys[sequences[[x]]], {x, 1, 30}];&#xD;
&#xD;
Testing the first method with a “Enigmatic” class scale sample, where we will get the musical notes and the prediction in the results. The result gives values and weights for both notes found and anti-values for notes not found on the scale. The result is this:&#xD;
&#xD;
![im2][3]&#xD;
&#xD;
    Table[Values@numb[[i]] -&amp;gt; &#xD;
       Subtract[Values[Counts[MemberQ[Keys@numb[[i]], #] &amp;amp; /@ test]][[1]],&#xD;
         Values[Counts[MemberQ[test, #] &amp;amp; /@ Keys@numb[[i]]]][[1]]], {i, &#xD;
       1, 30}] // Dataset[MaximalBy[#, Values, 5]] &amp;amp;&#xD;
&#xD;
![im3][4]&#xD;
&#xD;
Note that in the case above the scale was correctly identified, but this method is very fragile and for most scales and attempts the result is quite unsatisfactory.&#xD;
&#xD;
# Pitch Sound Note&#xD;
&#xD;
&#xD;
This next method relies more on the ability to recognize of the PitchRecognize command to recognize the frequencies, compared to the first method. The result is also given in valued scores and a prediction of which scale was used (in this case, a “Enigmatic” sample was also used):&#xD;
&#xD;
![im4][5]&#xD;
&#xD;
    Table[Values@numb[[i]] -&amp;gt; &#xD;
       Subtract[&#xD;
        Values[Counts[MemberQ[Keys@numb[[i]], #] &amp;amp; /@ test2]][[1]], &#xD;
        Values[Counts[MemberQ[test2, #] &amp;amp; /@ Keys@numb[[i]]]][[1]]], {i, &#xD;
       1, 30}] // Dataset[MaximalBy[#, Values, 5]] &amp;amp;&#xD;
&#xD;
![im5][6]&#xD;
&#xD;
Realize that the result was identical between the first two methods discussed, at least for the musical scale “Enigmatic” sample given. Normally, this method is also not very reliable and most of the time (with most musical scales) is wrong, which was tested, although in this case above I got it right.&#xD;
&#xD;
# Classify / Method Neural Net&#xD;
&#xD;
We will use a Neural Net classification method in this next attempt, to see if by this specific method the result is more satisfactory when working with Audio. First, we will generate a total of 50 samples of each type of musical scale class. Each sample in this case is 25.5 seconds in size formed with 5 random reproductions sequence by the specific scale. The tone will be maintained in all tests in “C3” with two octaves (default) and the playing method will always be mechanical for each note to have the same exact duration:&#xD;
&#xD;
    n = 50; samp1 = &#xD;
     RandomSample@&#xD;
      Flatten@Table[(Sound@&#xD;
             Table[ResourceFunction[&amp;#034;MusicalScaleSample&amp;#034;][#, &#xD;
               &amp;#034;Tone&amp;#034; -&amp;gt; &amp;#034;C3&amp;#034;, &amp;#034;NoteInterval&amp;#034; -&amp;gt; 0.15, &#xD;
               &amp;#034;Playing&amp;#034; -&amp;gt; &amp;#034;Mechanical&amp;#034;], 5] -&amp;gt; #) &amp;amp; /@ Keys@sequences, &#xD;
        n];&#xD;
&#xD;
Above, “samp1” was generated with 1500 samples, then changed to “stest1” with 300 samples to test the result of the classifiers. Now we can use Classify, as well as test it for the result and accuracy of the method:&#xD;
&#xD;
    c2 = Classify[samp1, Method -&amp;gt; &amp;#034;NeuralNetwork&amp;#034;]&#xD;
&#xD;
![im6][7]&#xD;
&#xD;
    ClassifierMeasurements[c2, stest1, &amp;#034;Accuracy&amp;#034;]&#xD;
&#xD;
![im7][8]&#xD;
&#xD;
As we can observe above, this method is far from being the best method to predict which musical scale in the case, it only gave a value of 8% accuracy!&#xD;
&#xD;
# Classify / Method Naive Bayes&#xD;
&#xD;
This next method is another option for the Classify function, an option that usually works best with Audio. Below we will see the result of the classifier with its prediction and accuracy:&#xD;
&#xD;
    c3 = Classify[samp1, Method -&amp;gt; &amp;#034;NaiveBayes&amp;#034;]&#xD;
&#xD;
![im8][9]&#xD;
&#xD;
    ClassifierMeasurements[c3, stest1, &amp;#034;Accuracy&amp;#034;]&#xD;
&#xD;
![im9][10]&#xD;
&#xD;
We see that by this method above (Naive Bayes), the result was already better to predict the original musical scale used, although it is still far from ideal, especially for some of the musical scales classes.&#xD;
&#xD;
# Customized ResNet&#xD;
&#xD;
The last method I tested in this work is by far the best method. First big difference is the transformation (Fourier) of Audio to its spectrum, since the classification of images proved to be a more powerful tool in this case. Below is an example of an Audio sample and its corresponding image to be classified by Machine Learning process:&#xD;
&#xD;
![im10][11]&#xD;
&#xD;
In order to generate the samples to be performed in the machine learning, some small modifications were made:&#xD;
&#xD;
- Instead of 5 reproductions followed by the scale in each sample, 10 reproductions were made, because more reproductions, it becomes clearer which is the identity of the scale.&#xD;
&#xD;
- A slightly higher value of the note interval was also used to make it easier to identify the sound of each note, this value was adapted together with the reproductions followed, so that, each sample has an exact 60 seconds of duration.&#xD;
&#xD;
- Another change was to directly specify the RasterSize and ImageSize for each sample to have a slightly better definition.&#xD;
&#xD;
Below, 100 samples of each scale class were generated, totaling 3000 samples (the time for this process was approximately 3 hours and the sample set size was just over 1GB):&#xD;
&#xD;
    n = 100; samp = &#xD;
     RandomSample@&#xD;
      Flatten@Table[(Rasterize[&#xD;
             Spectrogram[&#xD;
              Sound@Table[&#xD;
                ResourceFunction[&amp;#034;MusicalScaleSample&amp;#034;][#, &amp;#034;Tone&amp;#034; -&amp;gt; &amp;#034;C3&amp;#034;, &#xD;
                 &amp;#034;NoteInterval&amp;#034; -&amp;gt; 0.17646, &amp;#034;Playing&amp;#034; -&amp;gt; &amp;#034;Mechanical&amp;#034;], &#xD;
                10], Frame -&amp;gt; None], RasterSize -&amp;gt; 600, &#xD;
             ImageSize -&amp;gt; 300] -&amp;gt; #) &amp;amp; /@ Keys@sequences, n];&#xD;
&#xD;
The generator above was used also for a set: &amp;#034;stest&amp;#034; with 30 samples from each class totaling 900 total samples and a smaller set &amp;#034;stest2&amp;#034; of 15 samples from each class totaling 450 total samples.&#xD;
&#xD;
To better store these sample sets above I used DumpSave and the .MX file format:&#xD;
&#xD;
    filepath2 = FileNameJoin[{NotebookDirectory[], &amp;#034;samp.mx&amp;#034;}];&#xD;
    DumpSave[filepath2, {samp}];&#xD;
    filepath3 = FileNameJoin[{NotebookDirectory[], &amp;#034;stest.mx&amp;#034;}];&#xD;
    DumpSave[filepath3, {stest}];&#xD;
    filepath4 = FileNameJoin[{NotebookDirectory[], &amp;#034;stest2.mx&amp;#034;}];&#xD;
    DumpSave[filepath4, {stest2}];&#xD;
    Quit[]&#xD;
&#xD;
We can retrieve the sets with the simple Get command:&#xD;
&#xD;
    SetDirectory[NotebookDirectory[]];&#xD;
    Get[&amp;#034;samp.mx&amp;#034;]&#xD;
    Get[&amp;#034;stest.mx&amp;#034;]&#xD;
    Get[&amp;#034;stest2.mx&amp;#034;]&#xD;
&#xD;
Example of how the main set contains the samples and their definitions:&#xD;
&#xD;
    samp[[5 ;; 8]]&#xD;
&#xD;
![im11][12]&#xD;
&#xD;
We will now start to develop the customized NetChain. First, we create a directory for the classifier batches:&#xD;
&#xD;
    dirModel = CreateDirectory[];&#xD;
&#xD;
Than, we downloaded the ResNet, which in this case I used the **ResNet-152** from [Wolfram Neural Repository][13], but we discarded the last 3 layers in order to be able to customize the output and some characteristics of behavior:&#xD;
&#xD;
    tempNet = &#xD;
     Take[NetModel[&#xD;
       &amp;#034;ResNet-152 Trained on ImageNet Competition Data&amp;#034;], {1, -4}]&#xD;
&#xD;
![im12][14]&#xD;
&#xD;
We added some layers to increase the complexity and so that it can learn new features. Just as we defined, the 30 different classes of different musical scales to be used by the neural network:&#xD;
&#xD;
    newNet = NetChain[&amp;lt;|&amp;#034;pretrainedNet&amp;#034; -&amp;gt; tempNet, &#xD;
       &amp;#034;Flatten&amp;#034; -&amp;gt; FlattenLayer[], &amp;#034;Dropout1&amp;#034; -&amp;gt; DropoutLayer[0.2], &#xD;
       &amp;#034;linear&amp;#034; -&amp;gt; LinearLayer[1500], &amp;#034;Dropout2&amp;#034; -&amp;gt; DropoutLayer[0.2], &#xD;
       &amp;#034;linear2&amp;#034; -&amp;gt; LinearLayer[30],&#xD;
       &amp;#034;softmax&amp;#034; -&amp;gt; SoftmaxLayer[]|&amp;gt;, &#xD;
      &amp;#034;Output&amp;#034; -&amp;gt; &#xD;
       NetDecoder[{&amp;#034;Class&amp;#034;, {&amp;#034;MajorPentatonic&amp;#034;, &amp;#034;MinorPentatonic&amp;#034;, &#xD;
          &amp;#034;NeopolitanMajor&amp;#034;, &amp;#034;NeopolitanMinor&amp;#034;, &amp;#034;HungarianMajor&amp;#034;, &#xD;
          &amp;#034;HungarianMinor&amp;#034;, &amp;#034;HungarianGypsy&amp;#034;, &amp;#034;HarmonicMajor&amp;#034;, &#xD;
          &amp;#034;HarmonicMinor&amp;#034;, &amp;#034;DoubleHarmonic&amp;#034;, &amp;#034;JazzMinor&amp;#034;, &amp;#034;Overtone&amp;#034;, &#xD;
          &amp;#034;BluesScale&amp;#034;, &amp;#034;Chromatic&amp;#034;, &amp;#034;WholeTone&amp;#034;, &amp;#034;DiminishedWholeTone&amp;#034;, &#xD;
          &amp;#034;Symmetrical&amp;#034;, &amp;#034;Arabian&amp;#034;, &amp;#034;Balinese&amp;#034;, &amp;#034;Byzantine&amp;#034;, &amp;#034;Persian&amp;#034;, &#xD;
          &amp;#034;EastIndianPurvi&amp;#034;, &amp;#034;Oriental&amp;#034;, &amp;#034;GagakuRyoSenPou&amp;#034;, &amp;#034;Zokugaku&amp;#034;, &#xD;
          &amp;#034;InSenPou&amp;#034;, &amp;#034;Okinawa&amp;#034;, &amp;#034;Enigmatic&amp;#034;, &amp;#034;EightToneSpanish&amp;#034;, &#xD;
          &amp;#034;Prometheus&amp;#034;}}]]&#xD;
&#xD;
![im13][15]&#xD;
&#xD;
The network is ready to be trained. Below is an example of its learning:&#xD;
&#xD;
    trainedNet = &#xD;
     NetTrain[newNet, samp, ValidationSet -&amp;gt; stest, &#xD;
      TrainingProgressMeasurements -&amp;gt; {&amp;#034;ConfusionMatrixPlot&amp;#034;, &amp;#034;Accuracy&amp;#034;, &#xD;
        &amp;#034;Precision&amp;#034;, &amp;#034;Recall&amp;#034;}, &#xD;
      TrainingProgressCheckpointing -&amp;gt; {&amp;#034;Directory&amp;#034;, dirModel}, &#xD;
      BatchSize -&amp;gt; 16, MaxTrainingRounds -&amp;gt; 2]&#xD;
&#xD;
![im14][16]&#xD;
&#xD;
This was the final result of the learning:&#xD;
&#xD;
![im15][17]&#xD;
&#xD;
We can save the resulting NetChain also in an .MX file with DumpSave so that we can use it when necessary:&#xD;
&#xD;
    filepath5 = FileNameJoin[{NotebookDirectory[], &amp;#034;trainedNet.mx&amp;#034;}];&#xD;
    DumpSave[filepath5, {trainedNet}];&#xD;
&#xD;
With the code below we have, for example, the measures of global accuracy and the result of accuracy for each musical scale independently:&#xD;
&#xD;
    NetMeasurements[trainedNet, stest2 , &amp;#034;Accuracy&amp;#034;]&#xD;
    NetMeasurements[trainedNet, stest2, &amp;#034;F1Score&amp;#034;]&#xD;
    NetMeasurements[trainedNet, stest2, {&amp;lt;|&amp;#034;Measurement&amp;#034; -&amp;gt; &amp;#034;Precision&amp;#034;, &#xD;
       &amp;#034;ClassAveraging&amp;#034; -&amp;gt; &amp;#034;Macro&amp;#034;|&amp;gt;, &amp;lt;|&amp;#034;Measurement&amp;#034; -&amp;gt; &amp;#034;Recall&amp;#034;, &#xD;
       &amp;#034;ClassAveraging&amp;#034; -&amp;gt; &amp;#034;Macro&amp;#034;|&amp;gt;}]&#xD;
&#xD;
![im16][18]&#xD;
&#xD;
The same result of the independent scales measured separately, however, in the form of [ResourceFunction\[“NiceGrid”\]][19]:&#xD;
&#xD;
![im17][20]&#xD;
&#xD;
Let&amp;#039;s see how the result of the ConfusionMatrixPlot of the customized ResNet was performing for the classes of musical scales:&#xD;
&#xD;
    NetMeasurements[trainedNet, stest2, &amp;#034;ConfusionMatrixPlot&amp;#034;]&#xD;
&#xD;
![im18][21]&#xD;
&#xD;
To test the resulting custom NetChain, a function was created that generates a musical scale of choice and checks if the result was accurately predicted:&#xD;
&#xD;
    sampleMusic[scale_, opts_ : &amp;#034;Decision&amp;#034;] := &#xD;
     Module[{sound}, SetDirectory[NotebookDirectory[]]; &#xD;
      Get[&amp;#034;trainedNet.mx&amp;#034;]; &#xD;
      scale -&amp;gt; {trainedNet[&#xD;
          Rasterize[&#xD;
           Spectrogram[&#xD;
            sound = Sound@&#xD;
              Table[ResourceFunction[&amp;#034;MusicalScaleSample&amp;#034;][scale, &#xD;
                &amp;#034;Tone&amp;#034; -&amp;gt; &amp;#034;C3&amp;#034;, &amp;#034;NoteInterval&amp;#034; -&amp;gt; 0.17646, &#xD;
                &amp;#034;Playing&amp;#034; -&amp;gt; &amp;#034;Mechanical&amp;#034;], 10], Frame -&amp;gt; None], &#xD;
           RasterSize -&amp;gt; 600, ImageSize -&amp;gt; 300], opts] // Dataset, sound}]&#xD;
&#xD;
For example:&#xD;
&#xD;
    sampleMusic[&amp;#034;JazzMinor&amp;#034;]&#xD;
&#xD;
![im19][22]&#xD;
&#xD;
Above we see that it worked, the scale was recognized! Below is another sample of this class of musical scale with its probabilities:&#xD;
&#xD;
    sampleMusic[&amp;#034;JazzMinor&amp;#034;, &amp;#034;Probabilities&amp;#034;]&#xD;
&#xD;
![im20][23]&#xD;
&#xD;
# Conclusion (and Notes):&#xD;
&#xD;
Although the methods have not been explored extensively (especially the first ones), we can have an idea of the results of each approach.&#xD;
&#xD;
There are many other methods and options for each method, of course, in this work only a few were covered.&#xD;
&#xD;
The best method by far was the customized ResNet, which was more carefully prepared and had very satisfactory results for most musical scales. Only 3 of the 30 scale classes had an accuracy below 50% and with the vast majority (23 of 30) above 70%.&#xD;
&#xD;
It is clear that this work was a relatively simple work, in the sense that the conditions of recognition are controlled so that there is a satisfactory result, but nothing prevents the work from being extended to multiple situations in the future.&#xD;
&#xD;
- **Thanks:** I would like to thank [Siria Sadeddin][24], who gave me tips and guidance on the ResNet part. Thank you Siria!&#xD;
&#xD;
Thank you!&#xD;
&#xD;
&#xD;
  [1]: https://resources.wolframcloud.com/FunctionRepository/resources/MusicalScaleSample&#xD;
  [2]: https://community.wolfram.com//c/portal/getImageAttachment?filename=im1.png&amp;amp;userId=2108079&#xD;
  [3]: https://community.wolfram.com//c/portal/getImageAttachment?filename=test1mech.png&amp;amp;userId=2108079&#xD;
  [4]: https://community.wolfram.com//c/portal/getImageAttachment?filename=restest1mech.png&amp;amp;userId=2108079&#xD;
  [5]: https://community.wolfram.com//c/portal/getImageAttachment?filename=test2.png&amp;amp;userId=2108079&#xD;
  [6]: https://community.wolfram.com//c/portal/getImageAttachment?filename=restest2.png&amp;amp;userId=2108079&#xD;
  [7]: https://community.wolfram.com//c/portal/getImageAttachment?filename=baseneuralnet.png&amp;amp;userId=2108079&#xD;
  [8]: https://community.wolfram.com//c/portal/getImageAttachment?filename=resbaseneuralnet.png&amp;amp;userId=2108079&#xD;
  [9]: https://community.wolfram.com//c/portal/getImageAttachment?filename=basenaivetest.png&amp;amp;userId=2108079&#xD;
  [10]: https://community.wolfram.com//c/portal/getImageAttachment?filename=resbasenaivetest.png&amp;amp;userId=2108079&#xD;
  [11]: https://community.wolfram.com//c/portal/getImageAttachment?filename=spectroini.png&amp;amp;userId=2108079&#xD;
  [12]: https://community.wolfram.com//c/portal/getImageAttachment?filename=spectrosamp.png&amp;amp;userId=2108079&#xD;
  [13]: https://resources.wolframcloud.com/NeuralNetRepository&#xD;
  [14]: https://community.wolfram.com//c/portal/getImageAttachment?filename=netcrude.png&amp;amp;userId=2108079&#xD;
  [15]: https://community.wolfram.com//c/portal/getImageAttachment?filename=netcustom.png&amp;amp;userId=2108079&#xD;
  [16]: https://community.wolfram.com//c/portal/getImageAttachment?filename=learner.png&amp;amp;userId=2108079&#xD;
  [17]: https://community.wolfram.com//c/portal/getImageAttachment?filename=trainednet.png&amp;amp;userId=2108079&#xD;
  [18]: https://community.wolfram.com//c/portal/getImageAttachment?filename=netresult.png&amp;amp;userId=2108079&#xD;
  [19]: https://resources.wolframcloud.com/FunctionRepository/resources/NiceGrid&#xD;
  [20]: https://community.wolfram.com//c/portal/getImageAttachment?filename=nicegrid.png&amp;amp;userId=2108079&#xD;
  [21]: https://community.wolfram.com//c/portal/getImageAttachment?filename=confusionmatrixplot.png&amp;amp;userId=2108079&#xD;
  [22]: https://community.wolfram.com//c/portal/getImageAttachment?filename=res1.png&amp;amp;userId=2108079&#xD;
  [23]: https://community.wolfram.com//c/portal/getImageAttachment?filename=res2.png&amp;amp;userId=2108079&#xD;
  [24]: https://community.wolfram.com/web/siriasadeddin/home</description>
    <dc:creator>Claudio Chaib</dc:creator>
    <dc:date>2020-11-04T22:52:47Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1787163">
    <title>Converting OpenPose for Wolfram Language</title>
    <link>https://community.wolfram.com/groups/-/m/t/1787163</link>
    <description>Tuseeta-san&amp;#039;s [post][1] is how to convert a trained model of TensorFlow to Mathematica. Converting trained models from a language other than Mathematica to Mathematica is very beneficial to Mathematica users. So I&amp;#039;ll show how to convert a trained model of PyTorch to Mathematica along with Tuseeta-san&amp;#039;s post. &#xD;
![enter image description here][2]&#xD;
## Step 1: Figure out the architecture ##&#xD;
The [model][3] to be converted is Pose Estimation that detects the human skeleton (body parts and their connections) from an image. It&amp;#039;s called OpenPose.The model consists of Feature map that extracts image features and six Stage maps.&#xD;
Feature map extracts image features from an input image(size:368*368). Each  Stage map has two-branch, the first branch predicts confidence and the second predicts PAFs?Part Affinity Fields), along with the image feature .Two-branch are concatenated for next stage.&#xD;
## Step 2: Coding it in Mathematica ##&#xD;
**Feature map**&#xD;
&#xD;
The Feature map consists of the first 23 layers of VGG-19, followed by 2 sets of Convolution and Ramp.&#xD;
&#xD;
Extract the first 23 layers of VGG-19.&#xD;
&#xD;
    vgg19 = NetModel[&amp;#034;VGG-19 Trained on ImageNet Competition Data&amp;#034;];&#xD;
    vgg19sub = Take[vgg19, {1, 23}];&#xD;
&#xD;
Change Encoder.&#xD;
&#xD;
    enc = NetExtract[vgg19, &amp;#034;Input&amp;#034;];&#xD;
    enc = NetReplacePart[&#xD;
       enc, {&amp;#034;ImageSize&amp;#034; -&amp;gt; {368, 368}, &#xD;
        &amp;#034;VarianceImage&amp;#034; -&amp;gt; {0.229, 0.224, 0.225}, &#xD;
        &amp;#034;MeanImage&amp;#034; -&amp;gt; {0.485, 0.456, 0.406}}];&#xD;
    featurefirst = NetReplacePart[vgg19sub, &amp;#034;Input&amp;#034; -&amp;gt; enc];&#xD;
&#xD;
Add Convolution and Ramp.&#xD;
&#xD;
    feature = &#xD;
      NetAppend[&#xD;
       featurefirst, {&amp;#034;convadd1&amp;#034; -&amp;gt; &#xD;
         ConvolutionLayer[256, 3, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 1], &#xD;
        &amp;#034;reluadd1&amp;#034; -&amp;gt; Ramp,&#xD;
        &amp;#034;convadd2&amp;#034; -&amp;gt; &#xD;
         ConvolutionLayer[128, 3, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 1], &#xD;
        &amp;#034;reluadd2&amp;#034; -&amp;gt; Ramp}];&#xD;
&#xD;
**Stage map**&#xD;
&#xD;
Each Stage map consists only of Convolutions and Ramps.&#xD;
&#xD;
Stage 1: The differences between two branches is that the last output channel number is 38 or 19.&#xD;
&#xD;
    blk11 = NetChain[{&#xD;
        ConvolutionLayer[128, 3, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 1], Ramp,&#xD;
        ConvolutionLayer[128, 3, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 1], Ramp,&#xD;
        ConvolutionLayer[128, 3, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 1], Ramp,&#xD;
        ConvolutionLayer[512, 1, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 0], Ramp,&#xD;
        ConvolutionLayer[38, 1, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 0]}];&#xD;
    blk12 = NetChain[{&#xD;
        ConvolutionLayer[128, 3, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 1], Ramp,&#xD;
        ConvolutionLayer[128, 3, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 1], Ramp,&#xD;
        ConvolutionLayer[128, 3, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 1], Ramp,&#xD;
        ConvolutionLayer[512, 1, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 0], Ramp,&#xD;
        ConvolutionLayer[19, 1, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 0]}];&#xD;
&#xD;
Stage 2?6: The difference between Stage1 and Stage2?6 is the kinds and the numbers of layers.&#xD;
&#xD;
    blkx1 = NetChain[{&#xD;
        ConvolutionLayer[128, 7, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 3], Ramp,&#xD;
        ConvolutionLayer[128, 7, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 3], Ramp,&#xD;
        ConvolutionLayer[128, 7, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 3], Ramp,&#xD;
        ConvolutionLayer[128, 7, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 3], Ramp,&#xD;
        ConvolutionLayer[128, 7, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 3], Ramp,&#xD;
        ConvolutionLayer[128, 1, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 0], Ramp,&#xD;
        ConvolutionLayer[38, 1, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 0]}];&#xD;
    blkx2 = NetChain[{&#xD;
        ConvolutionLayer[128, 7, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 3], Ramp,&#xD;
        ConvolutionLayer[128, 7, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 3], Ramp,&#xD;
        ConvolutionLayer[128, 7, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 3], Ramp,&#xD;
        ConvolutionLayer[128, 7, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 3], Ramp,&#xD;
        ConvolutionLayer[128, 7, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 3], Ramp,&#xD;
        ConvolutionLayer[128, 1, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 0], Ramp,&#xD;
        ConvolutionLayer[19, 1, &amp;#034;Stride&amp;#034; -&amp;gt; 1, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 0]}];&#xD;
&#xD;
Finally, create OpenPose.&#xD;
&#xD;
    openpose = NetGraph[{&#xD;
       &amp;#034;feature&amp;#034; -&amp;gt; feature,(*feature*)&#xD;
       &amp;#034;blk11&amp;#034; -&amp;gt; blk11, &amp;#034;blk12&amp;#034; -&amp;gt; blk12,(*stage 1*)&#xD;
       &amp;#034;blk21&amp;#034; -&amp;gt; blkx1, &amp;#034;blk22&amp;#034; -&amp;gt; blkx2,(*stage 2*)&#xD;
       &amp;#034;cat12&amp;#034; -&amp;gt; CatenateLayer[],&#xD;
       &amp;#034;blk31&amp;#034; -&amp;gt; blkx1, &amp;#034;blk32&amp;#034; -&amp;gt; blkx2,(*stage 3*)&#xD;
       &amp;#034;cat23&amp;#034; -&amp;gt; CatenateLayer[],&#xD;
       &amp;#034;blk41&amp;#034; -&amp;gt; blkx1, &amp;#034;blk42&amp;#034; -&amp;gt; blkx2,(*stage 4*)&#xD;
       &amp;#034;cat34&amp;#034; -&amp;gt; CatenateLayer[],&#xD;
       &amp;#034;blk51&amp;#034; -&amp;gt; blkx1, &amp;#034;blk52&amp;#034; -&amp;gt; blkx2,(*stage 5*)&#xD;
       &amp;#034;cat45&amp;#034; -&amp;gt; CatenateLayer[],&#xD;
       &amp;#034;blk61&amp;#034; -&amp;gt; blkx1, &amp;#034;blk62&amp;#034; -&amp;gt; blkx2,(*stage 6*)&#xD;
       &amp;#034;cat56&amp;#034; -&amp;gt; CatenateLayer[]&#xD;
       },&#xD;
      {&amp;#034;feature&amp;#034; -&amp;gt; &amp;#034;blk11&amp;#034;, &amp;#034;feature&amp;#034; -&amp;gt; &amp;#034;blk12&amp;#034;,(*stage 1*)&#xD;
       {&amp;#034;blk11&amp;#034;, &amp;#034;blk12&amp;#034;, &amp;#034;feature&amp;#034;} -&amp;gt; &amp;#034;cat12&amp;#034;,(*stage 2*)&#xD;
       &amp;#034;cat12&amp;#034; -&amp;gt; &amp;#034;blk21&amp;#034;, &amp;#034;cat12&amp;#034; -&amp;gt; &amp;#034;blk22&amp;#034;,&#xD;
       {&amp;#034;blk21&amp;#034;, &amp;#034;blk22&amp;#034;, &amp;#034;feature&amp;#034;} -&amp;gt; &amp;#034;cat23&amp;#034;,(*stage 3*)&#xD;
       &amp;#034;cat23&amp;#034; -&amp;gt; &amp;#034;blk31&amp;#034;, &amp;#034;cat23&amp;#034; -&amp;gt; &amp;#034;blk32&amp;#034;,&#xD;
       {&amp;#034;blk31&amp;#034;, &amp;#034;blk32&amp;#034;, &amp;#034;feature&amp;#034;} -&amp;gt; &amp;#034;cat34&amp;#034;,(*stage 4*)&#xD;
       &amp;#034;cat34&amp;#034; -&amp;gt; &amp;#034;blk41&amp;#034;, &amp;#034;cat34&amp;#034; -&amp;gt; &amp;#034;blk42&amp;#034;,&#xD;
       {&amp;#034;blk41&amp;#034;, &amp;#034;blk42&amp;#034;, &amp;#034;feature&amp;#034;} -&amp;gt; &amp;#034;cat45&amp;#034;,(*stage 5*)&#xD;
       &amp;#034;cat45&amp;#034; -&amp;gt; &amp;#034;blk51&amp;#034;, &amp;#034;cat45&amp;#034; -&amp;gt; &amp;#034;blk52&amp;#034;,&#xD;
       {&amp;#034;blk51&amp;#034;, &amp;#034;blk52&amp;#034;, &amp;#034;feature&amp;#034;} -&amp;gt; &amp;#034;cat56&amp;#034;,(*stage 6*)&#xD;
       &amp;#034;cat56&amp;#034; -&amp;gt; &amp;#034;blk61&amp;#034;, &amp;#034;cat56&amp;#034; -&amp;gt; &amp;#034;blk62&amp;#034;&#xD;
       }]&#xD;
  &#xD;
![enter image description here][4]&#xD;
&#xD;
## Step 3: Importing the Weights and the Biases ##&#xD;
Download &amp;#034;[pose_model_scratch.pth][5]&amp;#034; as a trained model of PyTorch.&#xD;
&#xD;
Import the parameters, the weights and the biases. I referred &amp;#034;[How to import python pickle *.pkl?][6]&amp;#034;&#xD;
&#xD;
    session = StartExternalSession[&amp;#034;Python-NumPy&amp;#034;];&#xD;
    parameters = ExternalEvaluate[session, &amp;#034;import torch&#xD;
    import numpy as np&#xD;
    import pickle as pkl&#xD;
       &#xD;
    net_weights = torch.load(&#xD;
           &amp;#039;pose_model_scratch.pth&amp;#039;, map_location={&amp;#039;cuda:0&amp;#039;: &amp;#039;cpu&amp;#039;})&#xD;
    keys = list(net_weights.keys())&#xD;
       &#xD;
    parameters = {}&#xD;
    for i in range(len(keys)):&#xD;
           t = net_weights[keys[i]]       &#xD;
           x = t.numpy()&#xD;
           parameters[keys[i]] = x.flatten()&#xD;
    parameters&amp;#034;];&#xD;
    DeleteObject[session];&#xD;
    &#xD;
    keys = Keys[parameters];&#xD;
    parameters = Values[parameters];&#xD;
&#xD;
## Step 4: Parsing the Weights and the Biases ##&#xD;
&#xD;
The parameters is 184 sets of one-dimensional lists. They consists of the Weights and the Biases of 92 Convolution layers in OpenPose.&#xD;
&#xD;
Get a list of layer names for OpenPose with depth level. Then, get a list of 92 names where convolution layer is used in it.&#xD;
&#xD;
    layernames = &#xD;
      GroupBy[Keys@NetInformation[openpose, &amp;#034;Layers&amp;#034;], First] // Values;&#xD;
    convlayernames = (Position[&#xD;
         NetInformation[openpose, &amp;#034;Layers&amp;#034;], _ConvolutionLayer] // &#xD;
        Flatten)[[All, 1]]&#xD;
&#xD;
![enter image description here][7]&#xD;
&#xD;
As you can see in keys, you can see that the order of convolution layers of OpenPose is different from the order of convolution layers of &amp;#034;pose_model_scratch.pth&amp;#034; &#xD;
&#xD;
     keys&#xD;
&#xD;
![enter image description here][8]&#xD;
&#xD;
So, manually sort   the order of convolution layers in OpenPose into the order of &amp;#034;pose_model_scratch.pth&amp;#034;&#xD;
&#xD;
    convlayernamesGH = {{&amp;#034;feature&amp;#034;, &amp;#034;conv1_1&amp;#034;}, {&amp;#034;feature&amp;#034;, &amp;#034;conv1_2&amp;#034;},&#xD;
       {&amp;#034;feature&amp;#034;, &amp;#034;conv2_1&amp;#034;}, {&amp;#034;feature&amp;#034;, &amp;#034;conv2_2&amp;#034;},&#xD;
       {&amp;#034;feature&amp;#034;, &amp;#034;conv3_1&amp;#034;}, {&amp;#034;feature&amp;#034;, &amp;#034;conv3_2&amp;#034;}, {&amp;#034;feature&amp;#034;, &amp;#034;conv3_3&amp;#034;}, {&amp;#034;feature&amp;#034;, &amp;#034;conv3_4&amp;#034;},&#xD;
       {&amp;#034;feature&amp;#034;, &amp;#034;conv4_1&amp;#034;}, {&amp;#034;feature&amp;#034;, &amp;#034;conv4_2&amp;#034;},&#xD;
       {&amp;#034;feature&amp;#034;, &amp;#034;convadd1&amp;#034;}, {&amp;#034;feature&amp;#034;, &amp;#034;convadd2&amp;#034;},&#xD;
       {&amp;#034;blk11&amp;#034;, 1}, {&amp;#034;blk11&amp;#034;, 3}, {&amp;#034;blk11&amp;#034;, 5}, {&amp;#034;blk11&amp;#034;, 7}, {&amp;#034;blk11&amp;#034;, 9},&#xD;
       {&amp;#034;blk21&amp;#034;, 1}, {&amp;#034;blk21&amp;#034;, 3}, {&amp;#034;blk21&amp;#034;, 5}, {&amp;#034;blk21&amp;#034;, 7}, {&amp;#034;blk21&amp;#034;, 9}, {&amp;#034;blk21&amp;#034;, 11}, {&amp;#034;blk21&amp;#034;, 13},&#xD;
       {&amp;#034;blk31&amp;#034;, 1}, {&amp;#034;blk31&amp;#034;, 3}, {&amp;#034;blk31&amp;#034;, 5}, {&amp;#034;blk31&amp;#034;, 7}, {&amp;#034;blk31&amp;#034;, 9}, {&amp;#034;blk31&amp;#034;, 11}, {&amp;#034;blk31&amp;#034;, 13},&#xD;
       {&amp;#034;blk41&amp;#034;, 1}, {&amp;#034;blk41&amp;#034;, 3}, {&amp;#034;blk41&amp;#034;, 5}, {&amp;#034;blk41&amp;#034;, 7}, {&amp;#034;blk41&amp;#034;, 9}, {&amp;#034;blk41&amp;#034;, 11}, {&amp;#034;blk41&amp;#034;, 13},&#xD;
       {&amp;#034;blk51&amp;#034;, 1}, {&amp;#034;blk51&amp;#034;, 3}, {&amp;#034;blk51&amp;#034;, 5}, {&amp;#034;blk51&amp;#034;, 7}, {&amp;#034;blk51&amp;#034;, 9}, {&amp;#034;blk51&amp;#034;, 11}, {&amp;#034;blk51&amp;#034;, 13},&#xD;
       {&amp;#034;blk61&amp;#034;, 1}, {&amp;#034;blk61&amp;#034;, 3}, {&amp;#034;blk61&amp;#034;, 5}, {&amp;#034;blk61&amp;#034;, 7}, {&amp;#034;blk61&amp;#034;, 9}, {&amp;#034;blk61&amp;#034;, 11}, {&amp;#034;blk61&amp;#034;, 13},&#xD;
       {&amp;#034;blk12&amp;#034;, 1}, {&amp;#034;blk12&amp;#034;, 3}, {&amp;#034;blk12&amp;#034;, 5}, {&amp;#034;blk12&amp;#034;, 7}, {&amp;#034;blk12&amp;#034;, 9},&#xD;
       {&amp;#034;blk22&amp;#034;, 1}, {&amp;#034;blk22&amp;#034;, 3}, {&amp;#034;blk22&amp;#034;, 5}, {&amp;#034;blk22&amp;#034;, 7}, {&amp;#034;blk22&amp;#034;, 9}, {&amp;#034;blk22&amp;#034;, 11}, {&amp;#034;blk22&amp;#034;, 13},&#xD;
       {&amp;#034;blk32&amp;#034;, 1}, {&amp;#034;blk32&amp;#034;, 3}, {&amp;#034;blk32&amp;#034;, 5}, {&amp;#034;blk32&amp;#034;, 7}, {&amp;#034;blk32&amp;#034;, 9}, {&amp;#034;blk32&amp;#034;, 11}, {&amp;#034;blk32&amp;#034;, 13},&#xD;
       {&amp;#034;blk42&amp;#034;, 1}, {&amp;#034;blk42&amp;#034;, 3}, {&amp;#034;blk42&amp;#034;, 5}, {&amp;#034;blk42&amp;#034;, 7}, {&amp;#034;blk42&amp;#034;, 9}, {&amp;#034;blk42&amp;#034;, 11}, {&amp;#034;blk42&amp;#034;, 13},&#xD;
       {&amp;#034;blk52&amp;#034;, 1}, {&amp;#034;blk52&amp;#034;, 3}, {&amp;#034;blk52&amp;#034;, 5}, {&amp;#034;blk52&amp;#034;, 7}, {&amp;#034;blk52&amp;#034;, 9}, {&amp;#034;blk52&amp;#034;, 11}, {&amp;#034;blk52&amp;#034;, 13},&#xD;
       {&amp;#034;blk62&amp;#034;, 1}, {&amp;#034;blk62&amp;#034;, 3}, {&amp;#034;blk62&amp;#034;, 5}, {&amp;#034;blk62&amp;#034;, 7}, {&amp;#034;blk62&amp;#034;, 9}, {&amp;#034;blk62&amp;#034;, 11}, {&amp;#034;blk62&amp;#034;, 13}&#xD;
       };&#xD;
&#xD;
Get the position of each element of convlayernamesGH in OpenPose.&#xD;
&#xD;
    convlayerpos = &#xD;
     Flatten[Position[layernames, #] &amp;amp; /@ convlayernamesGH, 1]&#xD;
&#xD;
![enter image description here][9]&#xD;
&#xD;
Reshape each one-dimensional list of parameters to the dimension of the corresponding weight or bias.&#xD;
&#xD;
    getDimB[layer_] := Dimensions@NetExtract[layer, &amp;#034;Biases&amp;#034;]&#xD;
    getDimW[layer_] := Dimensions@NetExtract[layer, &amp;#034;Weights&amp;#034;]&#xD;
    convs = NetExtract[NetInitialize[openpose], #] &amp;amp; /@ convlayerpos;&#xD;
    dimW = getDimW /@ convs;&#xD;
    dimB = getDimB /@ convs;&#xD;
    dim = Flatten[Transpose[{dimW, dimB}], 1];&#xD;
    parametersReshape = MapThread[ArrayReshape, {parameters, dim}];&#xD;
&#xD;
## Step 5: Linking the Weights and the Biases ##&#xD;
Replace the initial values of weights and biases in OpenPose with learned parameters, and finally get trained OpenPose.&#xD;
&#xD;
    replacenames =&#xD;
      Flatten[&#xD;
       Transpose[{Flatten@{#, &amp;#034;Weights&amp;#034;} &amp;amp; /@ convlayernamesGH, &#xD;
         Flatten@{#, &amp;#034;Biases&amp;#034;} &amp;amp; /@ convlayernamesGH}], 1];&#xD;
    rule = Thread[replacenames -&amp;gt; parametersReshape];&#xD;
    trainedOpenPose = NetReplacePart[openpose, rule]&#xD;
&#xD;
![enter image description here][10]&#xD;
&#xD;
## Step 6: Making the tests ##&#xD;
For simplification, estimate pose for the image of single-person. The Output2 of OpenPose shows the confidence of 19 body parts in each part where the image is divided into 46 * 46.&#xD;
&#xD;
1:Nose, 2:Neck, 3:RShoulder, 4:RElbow, 5:RWrist, 6:LShoulder, 7:LElbow, 8:LWrist,&#xD;
9:RHip, 10:RKnee, 11:RAnkle, 12:LHip, 13:LKnee, 14:LAnkle, 15:REye, 16:LEye, 17:REar, 18:LEar, 19:Bkg&#xD;
&#xD;
Define the function to get the position of max of confidence of each body part.&#xD;
&#xD;
    maxpts[img_, confidences_, idex_] := Module[{pos, pts, h},&#xD;
      pos = Reverse@First@Position[h = confidences[[idex]], Max@h];&#xD;
      pts = (pos/46)*ImageDimensions@img; &#xD;
      pts = {pts[[1]], (ImageDimensions@img)[[2]] - pts[[2]]}&#xD;
      ]&#xD;
&#xD;
Connect the detected body parts and show the result together on the original image.&#xD;
&#xD;
    showpose[img_] := Module[{bodylist, size, out, confidences, pts, pose},&#xD;
      bodylist = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};&#xD;
      size = {368, 368};&#xD;
      out = trainedOpenPose[img];&#xD;
      confidences = out[[2]];&#xD;
      pts = maxpts[img, confidences, #] &amp;amp; /@ bodylist;&#xD;
      pose = Graphics[{&#xD;
         Yellow, Thickness[.0125], Line[pts[[#]] &amp;amp; /@ {1, 2}],&#xD;
         Green, Line[pts[[#]] &amp;amp; /@ {2, 3, 4, 5}],&#xD;
         Cyan, Line[pts[[#]] &amp;amp; /@ {2, 6, 7, 8}],&#xD;
         Orange, Line[pts[[#]] &amp;amp; /@ {2, 9, 10, 11}],&#xD;
         Magenta, Line[pts[[#]] &amp;amp; /@ {2, 12, 13, 14}],&#xD;
         PointSize[Large], Red, Point[pts],&#xD;
         White, Point[{{0, 0}, ImageDimensions@img}]&#xD;
         }, ImagePadding -&amp;gt; All];&#xD;
      Show[img, pose]&#xD;
      ]&#xD;
&#xD;
Let&amp;#039; try.&#xD;
&#xD;
    img = Import[&amp;#034;ichiro.jpg&amp;#034;];&#xD;
    showpose[img]&#xD;
&#xD;
![enter image description here][11]&#xD;
&#xD;
## Future work ##&#xD;
? Estimate the pose of an image in which multi-person are by using PAFs of output1 of OpenPose.&#xD;
&#xD;
? Convert a more accurate pose estimation model.&#xD;
&#xD;
&#xD;
  [1]: https://community.wolfram.com/groups/-/m/t/1785523&#xD;
  [2]: https://community.wolfram.com//c/portal/getImageAttachment?filename=00.jpg&amp;amp;userId=1013863&#xD;
  [3]: https://arxiv.org/pdf/1611.08050.pdf&#xD;
  [4]: https://community.wolfram.com//c/portal/getImageAttachment?filename=752004.jpg&amp;amp;userId=1013863&#xD;
  [5]: https://www.dropbox.com/s/ae071mfm2qoyc8v/pose_model.pth?dl=0&#xD;
  [6]: https://mathematica.stackexchange.com/questions/181273/how-to-import-%5C%20python-pickle-pkl?rq=1&#xD;
  [7]: https://community.wolfram.com//c/portal/getImageAttachment?filename=691905.jpg&amp;amp;userId=1013863&#xD;
  [8]: https://community.wolfram.com//c/portal/getImageAttachment?filename=387908.jpg&amp;amp;userId=1013863&#xD;
  [9]: https://community.wolfram.com//c/portal/getImageAttachment?filename=109406.jpg&amp;amp;userId=1013863&#xD;
  [10]: https://community.wolfram.com//c/portal/getImageAttachment?filename=179107.jpg&amp;amp;userId=1013863&#xD;
  [11]: https://community.wolfram.com//c/portal/getImageAttachment?filename=161401.jpg&amp;amp;userId=1013863</description>
    <dc:creator>Kotaro Okazaki</dc:creator>
    <dc:date>2019-09-10T21:36:49Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1207400">
    <title>Finding yoga-poses constellations in the night sky</title>
    <link>https://community.wolfram.com/groups/-/m/t/1207400</link>
    <description>![found constellations][9]&#xD;
&#xD;
## Story Time ##&#xD;
&#xD;
At its first meeting in 1922, the International Astronomical Union (IAU), officially adopted the list of 88 constellations that we use today.&#xD;
These include 14 men and women, 9 birds, two insects, 19 land animals, 10 water creatures, two centaurs, one head of hair, a serpent, a dragon, a flying horse, a river and 29 inanimate objects. As many of us have (frustratingly) witnessed first hand while star-gazing - most of these bear little resemblance to their supposed figures. Instead, it is more likely that the ancient constellation-makers meant them to be symbolic, a kind of celestial &amp;#034;Hall of Fame&amp;#034; for their favorite animals or heroes.&#xD;
&#xD;
This begs two questions I sought to answer with this project:&#xD;
&#xD;
 1. Can we &amp;#039;do better&amp;#039; now with the WL&amp;#039;s StarData[] curated data and Machine Learning functionality?&#xD;
 2. What if the ancient constellation-makers were slightly more creative? Say they looked up at the sky, and only saw yoga-poses!&#xD;
&#xD;
Some examples of the found yoga-pose constellations, projected on images of the night sky are shown here, with a walk-through of the code below:&#xD;
&#xD;
[![example yoga-pose constellations][1]][2]&#xD;
&#xD;
## Yoga Poses ##&#xD;
&#xD;
First things first, finding images for yoga poses.&#xD;
Turns out, the WL has a built in YogaPose Entity Class with 216(!) available entities and their schematics.&#xD;
A lot of these are very similar (e.g. palms facing up/down) and we therefore only select a subset of them, which differ substantially from each other:&#xD;
&#xD;
    yogaposes = EntityClass[&amp;#034;YogaPose&amp;#034;, All] // EntityList;&#xD;
    chosenPoses = &#xD;
      List /@ {4, 6, 7, 8, 11, 14, 23, 25, 28, 35, 38, 43, 51, 54, 56, 59,&#xD;
         63, 65, 71, 72, 76, 77, 78, 84, 88, 90, 98, 100, 102, 103, 110, &#xD;
        111, 112, 113, 116, 118, 119, 125, 126, 133, 139, 142, 149, 152, &#xD;
        153, 154, 155, 156, 160, 164, 165, 167, 172, 177, 178, 180, 182, &#xD;
        183, 184, 190, 193, 194, 195, 197, 202, 204, 206, 207, 209, 210, &#xD;
        212, 215, 216};&#xD;
    Shallow[Extract[yogaposes, chosenPoses]]&#xD;
&#xD;
We write a wrapper to ensure the schematics are padded to give a square image and visualize our 73 constellations:&#xD;
&#xD;
    makeSquare[gr_, size_, bool_: False] := &#xD;
     Block[{range, magnitudes, order, padding, newRanges, res},&#xD;
      range = AbsoluteOptions[gr, PlotRange][[1, 2]];&#xD;
      magnitudes = Abs[Subtract @@@ range];&#xD;
      order = Ordering[magnitudes, 2, Greater];&#xD;
      padding = Subtract @@ magnitudes[[order]]/2;&#xD;
      newRanges = {{-1, 1} padding + Last[range[[order]]], &#xD;
        First[range[[order]]]};&#xD;
      res = Show[gr, PlotRange -&amp;gt; Reverse@newRanges[[order]], &#xD;
        ImageSize -&amp;gt; size];&#xD;
      If[bool, Rasterize[res], res]]&#xD;
&#xD;
    Multicolumn[&#xD;
     makeSquare[#[&amp;#034;SimplifiedSchematic&amp;#034;], 64] &amp;amp; /@ &#xD;
      Most[Extract[yogaposes, chosenPoses]], 9, Frame -&amp;gt; All]&#xD;
&#xD;
![constellations graphic][3]&#xD;
&#xD;
## Neural Network ##&#xD;
Our problem now can be worded as a classification one: *given 5-10 stars, classify them as one of the 73 yoga-poses constellations*&#xD;
The problem with that formulation of-course is that 5-10 randomly selected points inside the constellation region isn&amp;#039;t specific enough to differentiate between constellations. The image below shows that although 1000 sets of 10 points will define the shape, 10 points alone fall short:&#xD;
&#xD;
![pointsInMesh][4] &#xD;
&#xD;
Instead, we compute the Voronoi diagram of the points, using DistanceTransform to leverage already-optimized convolutional neural nets used for classifying images. Note that, even if (naturally) the results are less clear with fewer points (left to right) - the result with only 10 points at the far right is still quite recognizable to a human eye:&#xD;
&#xD;
![distanceTransforms][5] &#xD;
&#xD;
With this in-mind, we create a neural network similar to the [VGG16][6] neural network, with successive 5x5 convolutions, ReLu activation functions and Max pooling layers. Finally note that we use an average pooling instead of fully connected layers to reduce the number of parameters and the use of dropout layers.&#xD;
&#xD;
    conv[output_] := ConvolutionLayer[output, {5, 5}, &amp;#034;PaddingSize&amp;#034; -&amp;gt; 2]&#xD;
    pool[size_] := PoolingLayer[{size, size}, &amp;#034;Stride&amp;#034; -&amp;gt; size]&#xD;
    lenet = NetChain[&#xD;
      {conv[32], Ramp, conv[32], Ramp, pool[2], conv[64], Ramp, conv[64], &#xD;
       Ramp, pool[2], conv[128], Ramp, conv[128], Ramp, conv[128], Ramp, &#xD;
       PoolingLayer[{9, 9}, &amp;#034;Stride&amp;#034; -&amp;gt; 9, &amp;#034;Function&amp;#034; -&amp;gt; Mean], &#xD;
       FlattenLayer[], DropoutLayer[], 73, SoftmaxLayer[]},&#xD;
      &amp;#034;Output&amp;#034; -&amp;gt; NetDecoder[{&amp;#034;Class&amp;#034;, Extract[yogaposes, chosenPoses]}],&#xD;
      &amp;#034;Input&amp;#034; -&amp;gt; NetEncoder[{&amp;#034;Image&amp;#034;, {64, 64}, ColorSpace -&amp;gt; &amp;#034;Grayscale&amp;#034;}]&#xD;
      ]&#xD;
&#xD;
The training set then consists of generating 10-15 points inside the constellation region (resized and padded to allow for rotations later), and taking their DistanceTransform:&#xD;
&#xD;
    meshes[n_] := &#xD;
     meshes[n] = &#xD;
      ImagePad[ColorNegate@&#xD;
        makeSquare[&#xD;
         yogaposes[[chosenPoses[[n, 1]]]][&amp;#034;SimplifiedSchematic&amp;#034;], 44], 10]&#xD;
    trainingSet[n_, m_, iter_] := &#xD;
     With[{reg = &#xD;
        ImageMesh[meshes[n], CornerNeighbors -&amp;gt; False, &#xD;
         Method -&amp;gt; &amp;#034;MarchingSquares&amp;#034;]},&#xD;
      Thread[ColorConvert[&#xD;
           ImageAdjust[&#xD;
            DistanceTransform[Image[SparseArray[# -&amp;gt; 0, {64, 64}, 1]]]], &#xD;
           &amp;#034;Grayscale&amp;#034;] &amp;amp; /@ &#xD;
         Clip[Round@RandomPoint[reg, {iter, m}], {1, 64}] -&amp;gt; &#xD;
        yogaposes[[chosenPoses[[n, 1]]]]]]&#xD;
    exampleTrainingSet = &#xD;
     Flatten[trainingSet[#, 10, 1] &amp;amp; /@ RandomInteger[{1, 73}, 10], 1]&#xD;
&#xD;
The net took a couple of hours to train on ~100,000 examples on my CPU.&#xD;
Here we import the trained net:&#xD;
&#xD;
    lenetTrained = Import[&amp;#034;constellationsNet.wlnet&amp;#034;]&#xD;
&#xD;
## Night Sky ##&#xD;
&#xD;
We&amp;#039;re almost ready to classify the night sky. We first need the location of the 10,000 brightest stars along with their Right Ascension and Declination:&#xD;
&#xD;
    brightest = &#xD;
     StarData[EntityClass[&#xD;
       &amp;#034;Star&amp;#034;, {EntityProperty[&amp;#034;Star&amp;#034;, &amp;#034;ApparentMagnitude&amp;#034;] -&amp;gt; &#xD;
         TakeSmallest[10000]}], {&amp;#034;RightAscension&amp;#034;, &amp;#034;Declination&amp;#034;, &#xD;
       &amp;#034;ApparentMagnitude&amp;#034;}]&#xD;
&#xD;
We can plot these on the night sky using no projection (i.e. RA Vs Dec), using the sinusoidal projection (taken by Kuba&amp;#039;s excellent [answer][7] in SE) or on the celestial sphere given by the following transformations respectively:&#xD;
&#xD;
$$sinusoidal:\{(\alpha -\pi ) \cos (\delta&#xD;
   ),\delta \}$$&#xD;
&#xD;
$$map  to3D:\{\cos (\alpha ) \cos (\delta ),\sin&#xD;
   (\alpha ) \cos (\delta ),\sin (\delta&#xD;
   )\}$$&#xD;
&#xD;
![brightestStarsProjections][8]&#xD;
&#xD;
## Classification ##&#xD;
&#xD;
Finally, we use these 10,000 brightest stars to compute a multivariate smooth kernel distribution out of which to sample from and a Nearest function to compute neighboring stars. We need to of-course use our own distance function on the celestial sphere:&#xD;
&#xD;
    wrap[list_] := Block[{xs, ys},&#xD;
      {xs, ys} = Transpose[list];&#xD;
      Thread[{Mod[xs, 2 \[Pi]], Mod[ys, \[Pi], -\[Pi]/2]}]]&#xD;
    mapTo3D[\[Alpha]_, \[Delta]_] = {Cos[\[Alpha]] Cos[\[Delta]], &#xD;
       Cos[\[Delta]] Sin[\[Alpha]], Sin[\[Delta]]};&#xD;
    dist[{u_, v_}, {x_, &#xD;
       y_}] := (#1[[1]] - #2[[1]])^2 + (#1[[2]] - #2[[2]])^2 + (#1[[&#xD;
           3]] - #2[[3]])^2 &amp;amp; @@ mapTo3D @@@ {{u, v}, {x, y}}&#xD;
    pts = wrap@QuantityMagnitude[UnitConvert[brightest[[6 ;;, ;; 2]]]];&#xD;
    nf = Nearest[pts, DistanceFunction -&amp;gt; dist]&#xD;
    sm = SmoothKernelDistribution[pts]&#xD;
&#xD;
Our search algorithm is therefore defined as follows:&#xD;
&#xD;
 1. Pick a random position from the night sky distribution&#xD;
 2. Compute its 5-10 nearest neighbors&#xD;
 3. Classify those stars and their rotations by $\frac{2 \pi }{15}$&#xD;
 4. Select the rotation which gives the highest accuracy&#xD;
 5. Associate constellation to running association and repeat&#xD;
&#xD;
        rescale[list_] := Block[{xs, ys},&#xD;
          {xs, ys} = Thread[list];&#xD;
          Thread[Rescale[#, MinMax[#], {11, 54}] &amp;amp; /@ {xs, ys}]]&#xD;
        rotate[\[Alpha]_, pts_] := &#xD;
         ImageAdjust@&#xD;
          DistanceTransform[&#xD;
           Image@SparseArray[&#xD;
             Round@RotationTransform[\[Alpha] , {65/2, 65/2}][rescale[pts]] -&amp;gt;&#xD;
               0, {64, 64}, 1]]&#xD;
        sky = &amp;lt;||&amp;gt;;&#xD;
        accumulate[] := &#xD;
         Block[{pts = &#xD;
            nf[Mod[RandomVariate[sm] + {0, \[Pi]}, 2 \[Pi]] - {0, \[Pi]}, &#xD;
             RandomInteger[{5, 10}]], \[Alpha], pred},&#xD;
          {\[Alpha], pred} = &#xD;
           Last[SortBy[&#xD;
             First /@ &#xD;
              Table[Thread[{\[Alpha], &#xD;
                 lenetTrained[rotate[\[Alpha], pts], &#xD;
                  &amp;#034;TopProbabilities&amp;#034;]}], {\[Alpha], 0, 2 \[Pi], (2 \[Pi])/&#xD;
                15}], Last]];&#xD;
          If[Not[KeyExistsQ[sky, pred[[1]]]] || &#xD;
            TrueQ[sky[pred[[1]], &amp;#034;Accuracy&amp;#034;] &amp;lt; pred[[2]]],&#xD;
           AssociateTo[sky, &#xD;
            pred[[1]] -&amp;gt; &amp;lt;|&amp;#034;Accuracy&amp;#034; -&amp;gt; pred[[2]], &#xD;
              &amp;#034;Image&amp;#034; -&amp;gt; &#xD;
               HighlightImage[&#xD;
                makeSquare[pred[[1]][&amp;#034;SimplifiedSchematic&amp;#034;], &#xD;
                 64], {PointSize[Medium], Red, &#xD;
                 Round[RotationTransform[\[Alpha], 65/2 {1, 1}][rescale@pts], &#xD;
                  0.5]}], &amp;#034;Points&amp;#034; -&amp;gt; pts, &amp;#034;Angle&amp;#034; -&amp;gt; \[Alpha]|&amp;gt;], Nothing];]&#xD;
&#xD;
We can import a precomputed association with 20 such constellations:&#xD;
&#xD;
    selectedAsc = Import[&amp;#034;skyAsc.m.gz&amp;#034;]&#xD;
&#xD;
## Results ##&#xD;
&#xD;
Finally, we orient the schematic based on the optimally found angle and (manually) connect the dots.&#xD;
&#xD;
    orient[pts_, \[Alpha]_] := &#xD;
     Round[RotationTransform[\[Alpha], 65/2 {1, 1}][rescale@pts], 0.5]&#xD;
    lines = {{{10, 7, 3, 1, 4, 9, 2, 5, 8}, {2, 6}}, {{7, 3, 1, 9, &#xD;
         6}, {10, 2, 1, 8}, {4, 3, 5}}, {{7, 8, 9, 4, 3, 2, 10}, {1, 2, 6,&#xD;
          5}}, {{10, 2, 1, 3, 9, 5}, {7, 1, 4, 6, 8}}, {{5, 4, 1, 2, &#xD;
         3}}, {{10, 4, 5, 7, 9, 3, 8}, {6, 1, 2, 3}}, {{9, 5, 6, 3, 1, 2, &#xD;
         7}, {7, 4, 8}}, {{7, 6, 2, 3, 5, 8}, {9, 5, 4}, {3, 1}}, {{6, 2, &#xD;
         1, 3, 4}, {2, 5}}, {{5, 6, 4, 1, 2, 8, 3, 7}}, {{10, 6, 3, 2, &#xD;
         7}, {5, 2, 1, 4, 9, 8}}, {{9, 5, 1, 2, 4, 8, 7}, {6, 3, 8}}, {{6,&#xD;
          10, 4, 2, 1, 3, 9, 7, 5, 8}}, {{6, 7, 3, 2, 1, 4, 5}}, {{10, 8, &#xD;
         3, 6, 7, 2, 5, 9}, {5, 1, 4, 3}}, {{6, 5, 2, 1, 3}, {1, 4}}, {{5,&#xD;
          1, 2, 3}, {1, 4}}, {{6, 3, 2, 1, 4}, {3, 5}, {2, 7}}, {{3, 6, 8,&#xD;
          2, 4, 5, 1, 7}}, {{3, 1, 2, 6, 5}}};&#xD;
    makeSquareAndScale[gr_, \[Alpha]_, size_, opacity_] := &#xD;
     Block[{range, magnitudes, order, padding, newRanges, s},&#xD;
      range = AbsoluteOptions[gr, PlotRange][[1, 2]];&#xD;
      magnitudes = Abs[Subtract @@@ range];&#xD;
      order = Ordering[magnitudes, 2, Greater];&#xD;
      padding = Subtract @@ magnitudes[[order]]/2;&#xD;
      s = size/First[magnitudes[[order]]];&#xD;
      newRanges = {{-1, 1} padding + Last[range[[order]]], &#xD;
        First[range[[order]]]};&#xD;
      Graphics[{Opacity[opacity], &#xD;
        GeometricTransformation[&#xD;
         GeometricTransformation[&#xD;
          gr[[1]], {ScalingMatrix[{s, &#xD;
             s}], -1 First /@ (s Reverse@newRanges[[order]])}], &#xD;
         RotationTransform[\[Alpha], (size + 1)/2 {1, 1}]]}, &#xD;
       ImageSize -&amp;gt; size]] &#xD;
    With[{l = Map[Line, lines, {2}]},&#xD;
     Multicolumn[&#xD;
      Table[Show[&#xD;
        makeSquareAndScale[&#xD;
         Keys[selectedAsc][[i]][&#xD;
          &amp;#034;SimplifiedSchematic&amp;#034;], -selectedAsc[[i, -1]], 64, 0.25], &#xD;
        Graphics[&#xD;
         GraphicsComplex[&#xD;
          rescale[selectedAsc[[i, -2]]], {l[[i]], Red, PointSize[Large], &#xD;
           Point /@ Sort /@ Flatten /@ lines[[i]]}]], &#xD;
        ImageSize -&amp;gt; 150], {i, 20}], 5, Frame -&amp;gt; All, &#xD;
      Appearance -&amp;gt; &amp;#034;Horizontal&amp;#034;]]&#xD;
&#xD;
![found constellations][9]&#xD;
&#xD;
These can also be superimposed on the full night-sky:&#xD;
&#xD;
    Graphics[{With[{l = Map[Line, lines, {2}]},&#xD;
       Table[GraphicsComplex[&#xD;
         selectedAsc[[i, -2]], {Orange, Thickness[Large], l[[i]], Red, &#xD;
          PointSize[Medium], Point /@ Sort /@ Flatten /@ lines[[i]]}], {i,&#xD;
          20}]], Opacity[0.25], PointSize[Small], &#xD;
      Point[Complement[pts, Flatten[Values@selectedAsc[[All, -2]], 1]]]}, &#xD;
     ImageSize -&amp;gt; 750]&#xD;
&#xD;
![found overlay][10]&#xD;
&#xD;
    sinusoidal[\[Alpha]_, \[Delta]_] = {(\[Alpha] - \[Pi]) Cos[\[Delta]], \&#xD;
    \[Delta]}&#xD;
    Graphics[{With[{l = Map[Line, lines, {2}]},&#xD;
       Table[GraphicsComplex[&#xD;
         sinusoidal @@@ selectedAsc[[i, -2]], {Orange, Thickness[Large], &#xD;
          l[[i]], Red, PointSize[Medium], &#xD;
          Point /@ Sort /@ Flatten /@ lines[[i]]}], {i, 20}]], &#xD;
      Opacity[0.25], PointSize[Small], &#xD;
      Point[sinusoidal @@@ &#xD;
        Complement[pts, Flatten[Values@selectedAsc[[All, -2]], 1]]]}, &#xD;
     ImageSize -&amp;gt; 750]&#xD;
&#xD;
![found sinusoidal][11]&#xD;
&#xD;
It is then a matter of Overlaying these found constellations to existing images of night skies to produce the images at the beginning of the post:&#xD;
&#xD;
    overlay[{img_, constellation_}, {size_, loc_, opac_}] := &#xD;
     ImageCompose[imgs[[img]], &#xD;
      ImageResize[&#xD;
       Show[makeSquareAndScale[&#xD;
         Keys[selectedAsc][[constellation]][&#xD;
          &amp;#034;SimplifiedSchematic&amp;#034;], -selectedAsc[[constellation, -1]], 64, &#xD;
         opac], Graphics[&#xD;
         GraphicsComplex[&#xD;
          rescale[selectedAsc[[constellation, -2]]], {White, &#xD;
           Thickness[0.0075], Line /@ lines[[constellation]], White, &#xD;
           PointSize[.025], &#xD;
           Point /@ Sort /@ Flatten /@ lines[[constellation]]}]], &#xD;
        ImageSize -&amp;gt; 1000], size], Scaled[loc]]&#xD;
&#xD;
## Conclusions / Lessons Learned ##&#xD;
 &#xD;
 - It IS possible to find collections of stars in the night sky matching all sorts of shapes. Other built-in entities to try are Pokemons, Dinosaurs etc&#xD;
 - Not all the found constellation work &amp;#039;perfectly&amp;#039;&#xD;
 - Machine Learning is a powerful tool, and the WL implementation makes it easy to get started&#xD;
 - Reformulating the problem to an easier, already solved problem (e.g. points -&amp;gt; 2D image input) can help Classification Accuracy&#xD;
 - Perhaps the most interesting aspect of neural networks now, is diversifying its applications - so be creative&#xD;
&#xD;
This work was presented at the 2017 WTC (as part of a larger talk entitled &amp;#034;(De)Generative Art&amp;#034;). &amp;lt;br&amp;gt;&#xD;
I look forward to any comments/suggestions.&#xD;
&amp;lt;br&amp;gt;&#xD;
&amp;lt;br&amp;gt;George&#xD;
&amp;lt;br&amp;gt;&#xD;
&amp;lt;br&amp;gt; PS The editor doesn&amp;#039;t seem to let me attach the .wlnet and .m.gz files.&#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=exampleImages.png&amp;amp;userId=11733&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=exampleImages.png&amp;amp;userId=616023&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=4214constellationsGraphic.png&amp;amp;userId=616023&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=randomPointsInmesh.png&amp;amp;userId=616023&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=distanceTransforms.png&amp;amp;userId=616023&#xD;
  [6]: https://arxiv.org/pdf/1409.1556v6.pdf&#xD;
  [7]: https://mathematica.stackexchange.com/questions/89668/geoprojection-for-astronomical-data-wrong-ticks/89792#89792&#xD;
  [8]: http://community.wolfram.com//c/portal/getImageAttachment?filename=maps.png&amp;amp;userId=616023&#xD;
  [9]: http://community.wolfram.com//c/portal/getImageAttachment?filename=foundConstellations.png&amp;amp;userId=616023&#xD;
  [10]: http://community.wolfram.com//c/portal/getImageAttachment?filename=overlaidConstellations.png&amp;amp;userId=616023&#xD;
  [11]: http://community.wolfram.com//c/portal/getImageAttachment?filename=overlaidConstellationsSinusoidal.png&amp;amp;userId=616023</description>
    <dc:creator>George Varnavides</dc:creator>
    <dc:date>2017-10-24T04:17:44Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1221098">
    <title>Classifying Japanese characters from the Edo period</title>
    <link>https://community.wolfram.com/groups/-/m/t/1221098</link>
    <description>Introduction&#xD;
----------&#xD;
&#xD;
I recently came across a post for a computer program that in some fields intends to compete with the Wolfram Language and which has a toolbox for Machine Learning. I wanted to compare the work described with the workflow in Mathematica. The challenge is to classify old Japanese Characters from texts from the so-called Edo period:&#xD;
&#xD;
    Style[StringTake[WikipediaData[&amp;#034;Edo period&amp;#034;], 601], 16]&#xD;
&#xD;
![enter image description here][1]&#xD;
&#xD;
The characters are written in running style and apparently are difficult to read for Japanese speakers today. We will use two approaches of machine learning in the Wolfram Language to tackle this problem. &#xD;
&#xD;
Historical Background&#xD;
-----------------------------&#xD;
&#xD;
Before we proceed, let&amp;#039;s have a look at the Tokugawa shogunate. I will use code borrow from [@Vitaliy Kaurov][at0] from his great article on [&amp;#034;Computational history: countries that are gone&amp;#034;][2]. The following lines compute the historic boundaries of the shogunate:&#xD;
&#xD;
    Monitor[tokugawaPOLY = &#xD;
       Table[EntityValue[Entity[&amp;#034;HistoricalCountry&amp;#034;, &amp;#034;TokugawaShogunate&amp;#034;],&#xD;
          EntityProperty[&amp;#034;HistoricalCountry&amp;#034;, &#xD;
          &amp;#034;Polygon&amp;#034;, {&amp;#034;Date&amp;#034; -&amp;gt; DateObject[{t}]}]], {t, 1600, 1870}];, t]&#xD;
&#xD;
We then only filter for &amp;#034;changes&amp;#034; in the boundaries:&#xD;
&#xD;
    tokugawaPOLY // Length&#xD;
    tokugawaPOLYcomp = &#xD;
      DeleteMissing[&#xD;
       DeleteDuplicates[Transpose[{Range[1600, 1870], tokugawaPOLY}], &#xD;
        Last[#1] == Last[#2] &amp;amp;], 1, 2];&#xD;
    tokugawaPOLYcomp // Length&#xD;
&#xD;
In the 271 I consider in the first place there are only 4 changes to the boarders, which we can plot like so:&#xD;
&#xD;
    GeoGraphics[{EdgeForm[Red], GeoStyling[Opacity[.1]], #} &amp;amp; /@ &#xD;
      tokugawaPOLYcomp[[All, 2]], GeoProjection -&amp;gt; &amp;#034;Mercator&amp;#034;, &#xD;
     ImageSize -&amp;gt; 800, GeoBackground -&amp;gt; GeoStyling[&amp;#034;StreetMap&amp;#034;], &#xD;
     GeoRange -&amp;gt; Entity[&amp;#034;Country&amp;#034;, &amp;#034;Japan&amp;#034;], &#xD;
     GeoRangePadding -&amp;gt; Quantity[800, &amp;#034;Kilometers&amp;#034;], GeoZoomLevel -&amp;gt; 6]&#xD;
&#xD;
![enter image description here][3]&#xD;
&#xD;
So the boarders were indeed very stable for a long period reflecting the &amp;#034;no more wars&amp;#034; philosophy of the day.&#xD;
&#xD;
Arts and culture&#xD;
----------&#xD;
&#xD;
 The stability led to a very rich art and literature scene. Here are some images that reflect the style of the time:&#xD;
&#xD;
    ImageCollage[&amp;#034;Thumbnail&amp;#034; /. Normal[Normal[WebImageSearch[&amp;#034;Edo Period&amp;#034;]]], Method -&amp;gt; &amp;#034;Rows&amp;#034;]&#xD;
&#xD;
![enter image description here][4]&#xD;
&#xD;
Our dataset&#xD;
----------&#xD;
&#xD;
Also literature flourished during this period. Our dataset will be taken from the [Center for Open Data in the Humanities][5]. The keen reader might have noticed that the page is in Japanese. Mathematica can translate the page, and [so can Google][6]. The dataset is called the &amp;#034;Japanese classic registered glyph data set&amp;#034;; ?????????????.&#xD;
&#xD;
    TextTranslation[&amp;#034;?????????????&amp;#034;]&#xD;
&#xD;
&amp;#034;Japan classics-type datasets&amp;#034;. Following the first link (grey box) on the original Japanese page one gets to t[his page][7], from the bottom of which (look for a download symbol and the text &amp;#034;(TAR+GZ 24.57 MB)&amp;#034; the dataset can be downloaded. This is the google translation of the reference:&#xD;
&#xD;
&amp;gt; Japanese Classic Statement Character Data Set&amp;#034; (Kokugaku Kenkyu Other&#xD;
&amp;gt; Collection / CODH Processing)&#xD;
&#xD;
which in the original is &amp;#034;???????????????????????CODH??&amp;#034;.&#xD;
&#xD;
The glyphs come from &amp;#034;bamboo letters&amp;#034; from 15 classic texts; the dataset contains more than 20000 glyphs of the 10 most frequent symbols. These letters were annotated by the &amp;#034;National Institute of Letters of Japan&amp;#034; (google). The dataset was also used in a [data/machine learning challenge][8].&#xD;
&#xD;
After extracting the file to a folder on the desktop I can import the images with:&#xD;
&#xD;
    characterImages = Import[&amp;#034;/Users/thiel/Desktop/pmjt_sample_20161116/train_test_file_list.h5&amp;#034;, &amp;#034;Data&amp;#034;];&#xD;
&#xD;
Here is a sample of the glyphs:&#xD;
&#xD;
    Grid[Partition[ImageAdjust[Image[#/256.]] &amp;amp; /@ characterImages[[3, 1 ;; 24]], 6], Frame -&amp;gt; All]&#xD;
&#xD;
![enter image description here][9]&#xD;
&#xD;
Similar to the MNIST dataset, they consist of 28 times 28 pixels. They give the grey level as integers, which is why I divide by 256. This shows the pixelation of the glyphs:&#xD;
&#xD;
    Image[characterImages[[3, 12]]/256.] // ImageAdjust&#xD;
&#xD;
![enter image description here][10]&#xD;
&#xD;
The dataset conveniently contains a training and a test set. There are &#xD;
&#xD;
    characterImages[[3]] // Length&#xD;
&#xD;
19909 glyphs in the training set. All of these are annotated:&#xD;
&#xD;
    Flatten[characterImages[[4]]]&#xD;
&#xD;
![enter image description here][11]&#xD;
&#xD;
We can convert the training data to images like so:&#xD;
&#xD;
Monitor[trainingset = Table[ImageAdjust[Image[characterImages[[3, k]]/256.]] -&amp;gt; Flatten[characterImages[[4]]][[k]], {k, 1, 19909}];, k]&#xD;
&#xD;
The test set contains &#xD;
&#xD;
    characterImages[[1]] // Length&#xD;
&#xD;
3514 glyphs. The annotation of which are found in&#xD;
&#xD;
    characterImages[[2]] // Flatten // Short&#xD;
&#xD;
![enter image description here][12]&#xD;
&#xD;
This is how we prepare the test set data for our machine learning:&#xD;
&#xD;
    Monitor[testset = Table[ImageAdjust[Image[characterImages[[1, k]]/256.]] -&amp;gt; Flatten[characterImages[[2]]][[k]], {k, 1, 3514}];, k]&#xD;
&#xD;
What are the 10 most frequent symbols?&#xD;
----------&#xD;
&#xD;
In one of the annotation files we find the character codes of the symbols so that we can map the classification to actual symbols. These are the glyphs we will consider:&#xD;
&#xD;
    Rasterize /@ (Style[&#xD;
         FromCharacterCode[&#xD;
          ToExpression[&amp;#034;16^^&amp;#034; &amp;lt;&amp;gt; StringJoin[Characters[#]]]], &#xD;
         100] &amp;amp; /@ {&amp;#034;3057&amp;#034;, &amp;#034;306B&amp;#034;, &amp;#034;306E&amp;#034;, &amp;#034;3066&amp;#034;, &amp;#034;308A&amp;#034;, &amp;#034;3092&amp;#034;, &#xD;
        &amp;#034;304B&amp;#034;, &amp;#034;304F&amp;#034;, &amp;#034;304D&amp;#034;, &amp;#034;3082&amp;#034;})&#xD;
&#xD;
![enter image description here][13]&#xD;
&#xD;
We can also make an image collage of them:&#xD;
&#xD;
    ImageCollage[&#xD;
     Image /@ (Rasterize /@ (Style[&#xD;
            FromCharacterCode[&#xD;
             ToExpression[&amp;#034;16^^&amp;#034; &amp;lt;&amp;gt; StringJoin[Characters[#]]]], &#xD;
            100] &amp;amp; /@ {&amp;#034;3057&amp;#034;, &amp;#034;306B&amp;#034;, &amp;#034;306E&amp;#034;, &amp;#034;3066&amp;#034;, &amp;#034;308A&amp;#034;, &amp;#034;3092&amp;#034;, &#xD;
           &amp;#034;304B&amp;#034;, &amp;#034;304F&amp;#034;, &amp;#034;304D&amp;#034;, &amp;#034;3082&amp;#034;})), Method -&amp;gt; &amp;#034;Rows&amp;#034;]&#xD;
&#xD;
![enter image description here][14]&#xD;
&#xD;
I though it would be nice if they were in a more calligraphic form. So I tried to used ImageRestyle to try and make them more calligraphic. I think that the attempt was not very successful, but I want to show it anyway.&#xD;
&#xD;
First I download a couple of calligraphic symbols:&#xD;
&#xD;
    caligraphy = &amp;#034;Thumbnail&amp;#034; /. Normal[Normal[WebImageSearch[&amp;#034;japanese calligraphy&amp;#034;]]]&#xD;
&#xD;
I liked the 5th one, which I will use for the style transfer:&#xD;
&#xD;
    calisymbols = &#xD;
     ImageRestyle[#, caligraphy[[5]], &#xD;
        PerformanceGoal -&amp;gt; &#xD;
         &amp;#034;Quality&amp;#034;] &amp;amp; /@ (Rasterize /@ (Style[&#xD;
            FromCharacterCode[&#xD;
             ToExpression[&amp;#034;16^^&amp;#034; &amp;lt;&amp;gt; StringJoin[Characters[#]]]], &#xD;
            100] &amp;amp; /@ {&amp;#034;3057&amp;#034;, &amp;#034;306B&amp;#034;, &amp;#034;306E&amp;#034;, &amp;#034;3066&amp;#034;, &amp;#034;308A&amp;#034;, &amp;#034;3092&amp;#034;, &#xD;
           &amp;#034;304B&amp;#034;, &amp;#034;304F&amp;#034;, &amp;#034;304D&amp;#034;, &amp;#034;3082&amp;#034;}))&#xD;
&#xD;
![enter image description here][15]&#xD;
&#xD;
We can also remove the background to get an alternative representation:&#xD;
&#xD;
![enter image description here][16]&#xD;
&#xD;
Machine Learning (Classify)&#xD;
----------&#xD;
&#xD;
&#xD;
Our first approach to classify the glyphs will be via Classify. The classification is very fast (only a couple of seconds on my machine) and quite accurate:&#xD;
&#xD;
    standardcl = Classify[trainingset, ValidationSet -&amp;gt; testset, PerformanceGoal -&amp;gt; &amp;#034;Quality&amp;#034;]&#xD;
&#xD;
We can first calculate the ClassifierMeasurements&#xD;
&#xD;
    cmstandard = ClassifierMeasurements[standardcl, testset]&#xD;
&#xD;
and the accuracy:&#xD;
&#xD;
    cmstandard[&amp;#034;Accuracy&amp;#034;]&#xD;
&#xD;
With 92.5% this is quite accurate and also much faster than the competitor product. The confusion plot shows that it is a very reasonable accuracy - in particular when considering that native speakers have problems identifying the glyphs.  &#xD;
&#xD;
    cmstandard[&amp;#034;ConfusionMatrixPlot&amp;#034;]&#xD;
&#xD;
![enter image description here][17]&#xD;
&#xD;
Here are some glyphs that the Classifier identified as class &amp;#034;0&amp;#034;:&#xD;
&#xD;
    cmstandard[&amp;#034;Examples&amp;#034; -&amp;gt; {0, 0}][[1 ;; 20]]&#xD;
&#xD;
![enter image description here][18]&#xD;
&#xD;
They look quite diverse, but so does the original set:&#xD;
&#xD;
    RandomSample[Select[trainingset, #[[2]] == 0 &amp;amp;], 20]&#xD;
&#xD;
![enter image description here][19]&#xD;
&#xD;
It is quite impressive that the Classify function manages to achieve this level of accuracy. We can, however, do better!&#xD;
&#xD;
Machine Learning (NetTrain)&#xD;
----------&#xD;
&#xD;
We can improve the accuracy by training our own custom made network, which in this case will be the standard net that is often used for the MNIST dataset in Mathematica. It turns out that we do not even need a GPU for the training. &#xD;
&#xD;
    lenet = NetChain[{ConvolutionLayer[20, 5], Ramp, PoolingLayer[2, 2], &#xD;
       ConvolutionLayer[50, 5], Ramp, PoolingLayer[2, 2], FlattenLayer[], &#xD;
       500, Ramp, 10, SoftmaxLayer[]}, &#xD;
      &amp;#034;Output&amp;#034; -&amp;gt; NetDecoder[{&amp;#034;Class&amp;#034;, Range[0, 9]}], &#xD;
      &amp;#034;Input&amp;#034; -&amp;gt; NetEncoder[{&amp;#034;Image&amp;#034;, {28, 28}, &amp;#034;Grayscale&amp;#034;}]]&#xD;
&#xD;
![enter image description here][20]&#xD;
&#xD;
This we can then train:&#xD;
&#xD;
    lenet = NetTrain[lenet, trainingset, ValidationSet -&amp;gt; testset, MaxTrainingRounds -&amp;gt; 20];&#xD;
&#xD;
![enter image description here][21]&#xD;
&#xD;
The training is done in about 4:30 minutes, but it appears that 20 training rounds are not necessary. Here are some results when applying the classifier:&#xD;
&#xD;
    imgs = Keys@RandomSample[testset, 60]; Thread[imgs -&amp;gt; lenet[imgs]]&#xD;
&#xD;
![enter image description here][22]&#xD;
&#xD;
Let&amp;#039;s see how well it does:&#xD;
&#xD;
    cm = ClassifierMeasurements[lenet, testset]&#xD;
    cm[&amp;#034;ConfusionMatrixPlot&amp;#034;]&#xD;
&#xD;
![enter image description here][23]&#xD;
&#xD;
This corresponds to an accuracy of &#xD;
&#xD;
    cm[&amp;#034;Accuracy&amp;#034;]&#xD;
&#xD;
95.6%, which is really impressive given the dataset. The following table illustrates the difficulty:&#xD;
&#xD;
    Grid[Table[&#xD;
    Prepend[Select[trainingset, #[[2]] == k &amp;amp;][[1 ;; 10]][[All, 1]], &#xD;
    ImageResize[calisymbols[[k + 1]], 28]], {k, 0, 9}], Frame -&amp;gt; All, &#xD;
    Background -&amp;gt; {{Red}, None}]&#xD;
&#xD;
![enter image description here][24]&#xD;
&#xD;
The first (red) column is derived from the glyph based on the character code - using our &amp;#034;calligraphy-style&amp;#034;. The remaining columns show items from the training set, i.e. glyphs that were manually classified to belong to the given group.&#xD;
&#xD;
Conclusion&#xD;
----------&#xD;
&#xD;
I do not speak/read Japanese and have no more than Wikipedia knowledge about the Edo period. I still find it quite amazing that using the Wolfram Language&amp;#039;s high level Classify function and one of the pre-implemented networks, we can achieve quite a remarkable classification. I am sure that the network can be improved. I would also like to see a more complete dataset with more than 10 different symbols.  &#xD;
&#xD;
&#xD;
 [at0]: http://community.wolfram.com/web/vitaliyk&#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-13at23.24.03.png&amp;amp;userId=48754&#xD;
  [2]: http://community.wolfram.com/groups/-/m/t/852277&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-13at23.30.18.png&amp;amp;userId=48754&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-13at23.33.24.png&amp;amp;userId=48754&#xD;
  [5]: http://codh.rois.ac.jp/char-shape/&#xD;
  [6]: https://translate.google.com/translate?hl=en&amp;amp;sl=auto&amp;amp;tl=en&amp;amp;u=http://codh.rois.ac.jp/char-shape/&#xD;
  [7]: http://codh.rois.ac.jp/char-shape/book/&#xD;
  [8]: https://translate.google.com/translate?hl=en&amp;amp;sl=ja&amp;amp;tl=en&amp;amp;u=http://codh.rois.ac.jp/seminar/japanese-character-challenge-20170210/&amp;amp;sandbox=1&#xD;
  [9]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-13at23.56.19.png&amp;amp;userId=48754&#xD;
  [10]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-13at23.57.57.png&amp;amp;userId=48754&#xD;
  [11]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-13at23.59.36.png&amp;amp;userId=48754&#xD;
  [12]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.01.19.png&amp;amp;userId=48754&#xD;
  [13]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.04.22.png&amp;amp;userId=48754&#xD;
  [14]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.05.04.png&amp;amp;userId=48754&#xD;
  [15]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.07.44.png&amp;amp;userId=48754&#xD;
  [16]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.08.53.png&amp;amp;userId=48754&#xD;
  [17]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.15.09.png&amp;amp;userId=48754&#xD;
  [18]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.17.07.png&amp;amp;userId=48754&#xD;
  [19]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.18.25.png&amp;amp;userId=48754&#xD;
  [20]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.21.43.png&amp;amp;userId=48754&#xD;
  [21]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.22.50.png&amp;amp;userId=48754&#xD;
  [22]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.27.23.png&amp;amp;userId=48754&#xD;
  [23]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.28.27.png&amp;amp;userId=48754&#xD;
  [24]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2017-11-14at00.40.41.png&amp;amp;userId=48754</description>
    <dc:creator>Marco Thiel</dc:creator>
    <dc:date>2017-11-14T00:49:30Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/480226">
    <title>Predictive Analytics in Finance</title>
    <link>https://community.wolfram.com/groups/-/m/t/480226</link>
    <description>We extend the discussion on machine learning one step further and focus on predictive analysis offered in the ML domain. Prediction builds on classification and clustering techniques discussed previously and uses pattern detection and similarity features in data to estimate the future outcome. This is particularly relevant to finance where the ability of data groups to predict the values of less-liquid instruments is of high interest. We demonstrate the prediction using CDS data and show the application of non-regression models as superior methods for predictive analysis.&#xD;
&#xD;
![PA image][1]&#xD;
&#xD;
#Introduction#&#xD;
&#xD;
Classification and clustering which we discussed in previous installments naturally extends into another field of data mining - **prediction**.  It is well-known that there will be limited benefit of massive amount of data collection if the data cannot be analysed, decomposed into signals and used to predict future behaviour. Therefore, data analysis in statistics and econometrics can be broken down into four major categories:  (i) prediction, (ii) summarisation, (iii) estimation, and (iv) hypothesis testing. Machine learning , as we have stated previously,  focuses primarily  at data organisation and prediction. However, closely related  field is also data summarisation  where pattern finding in the data - covered by the classification - is of primary interest. Machine learning is therefore about developing high-performance computer systems that can provide useful predictions in the presence of challenging computational constraints. This whole area of data processing is today routinely described as **data science**, which is  primarily looks at both prediction and summarisation, but also extends into data manipulation, visualization, and other similar tasks.&#xD;
&#xD;
In pure statistical terms, the prediction problem reduces to finding *conditional distribution* of some variable y given some other variables  $x= (x_ 1,x_ 2,...x_n)$. In data science methodology, variables x are called &amp;#039;predictors&amp;#039; or &amp;#039;features&amp;#039;. The prediction point y is generally the highest value (mean) of the calibrated conditional distribution.&#xD;
&#xD;
#Prediction basics#&#xD;
&#xD;
Much of applied econometrics, economics and finance is concerned with detecting and summarising relationships in the data. The most common tool is (linear) regression analysis. Machine learning offers richer set of tools that can usefully summarise various sorts of nonlinear relationships in the data. We will focus on these regression-like tools because they are the most natural for economic and financial applications.&#xD;
&#xD;
The objective of prediction is to find some function that gives a good estimate of y as function of x. In machine learning context the data we work with are generally considered independent and identically distributed. They may be &amp;#039;fat&amp;#039; which implies more predictors relative to observations or &amp;#039;tall&amp;#039; which indicated many observations relative to predictors. &#xD;
&#xD;
When we build prediction routines, we start with some observation of y and  x and then want to  obtain the predicted point for the new value x .&amp;#039;Good&amp;#039; prediction involves  finding a function that minimises some error estimation. Sum of squared residuals, mean residual value are generally the most frequently used tools in this context. Tradition all method to solve this problem is regression - typically linear or logistic However, machine learning offers better options especially when there is a lot of data available.  These include trees, nearest neighbors, random forests or neural networks.  &#xD;
&#xD;
#Working with predictions#&#xD;
&#xD;
Objective of prediction routines is to find good out-of-sample estimation to the data. This task is not always trivial and regressions are generally known to be &amp;#039;weak&amp;#039; around out-of-sample predictions. This is generally known as &amp;#039;overfitting&amp;#039; problem. Machine learning addresses this problem through:&#xD;
&#xD;
 - Regularisation - preference is given to simpler models&#xD;
 - Dataset division into (i) training and (ii) testing sets&#xD;
 - Cross-validation of the dataset and the model&#xD;
&#xD;
#Prediction relation to other data mining techniques#&#xD;
Irrespective of the method structure, there is a common confusion between explanatory and predictive models. In a predictive model only the model&amp;#039;s accuracy is important and the structure of the model is relatively unimportant, as long as it is robust. In general, models become more robust as the number of predictors declines, and hence there is a greater tendency towards parsimony in predictive models, often using variable selection algorithms.&#xD;
&#xD;
However, if a model is developed for explanatory purposes, the identity and weights of the predictors is the most important part of the model because these are used to infer the nature of the relationship between the class and the values of the predictor variables.&#xD;
&#xD;
The contribution made by the predictors is obviously most important in an explanatory, rather than a predictive, model. In predictive models the role of predictors is less important than the accuracy of the prediction. Consequently, the use of variable selection routines that produce a more parsimonious model are generally more acceptable in predictive models.&#xD;
#Prediction in Finance#&#xD;
The advantages offered by machine learning are well suited for the data analysis in finance, particularly when the larger datasets are available. For years, the regression technique was dominant in economics and finance on the premise of limited amount of data. However,nowadays, in data-rich era, there is no reason not to start applying machine learning methods more frequently in economic and financial industries with data separation or the use of validation sets.&#xD;
##Problem definition##&#xD;
Let&amp;#039;s define the following problem: we have available set of actively traded and liquid CDS rates ( 5 years of daily rates) that we would like to use for prediction of lesser liquid CDS. These types of problem frequently occur in the credit or equity markets where liquidity factor drives certain instruments into specific categories.&#xD;
&#xD;
 - 3 CDS will serve as features&#xD;
 - We split the data into three sets: (i) training, (ii) testing and&#xD;
   (iii) validation&#xD;
 - We apply several predictive routines to obtain the future value in&#xD;
   the out-of-sample domain&#xD;
&#xD;
##Data generation##&#xD;
&#xD;
    vols = {0.01, 0.008, 0.011, 0.008};&#xD;
    crl = ({&#xD;
        {1, 0.35, 0.45, 0.36},&#xD;
        {0.35, 1, 0.43, 0.32},&#xD;
        {0.45, 0.43, 1, 0.46},&#xD;
        {0.36, 0.32, 0.46, 1}&#xD;
       });&#xD;
    cm = Table[vols[[i]]*vols[[j]]*crl[[i, j]], {i, 1, Length[vols]}, {j, 1, Length[vols]}]&#xD;
&#xD;
&amp;gt; {{0.0001, 0.000028, 0.0000495, 0.0000288}, {0.000028, 0.000064, &#xD;
  0.00003784, 0.00002048}, {0.0000495, 0.00003784, 0.000121, &#xD;
  0.00004048}, {0.0000288, 0.00002048, 0.00004048, 0.000064}}&#xD;
&#xD;
    init = {0.55, 0.72, 1.25, 1};&#xD;
    mn = MultinormalDistribution[{0, 0, 0, 0}, cm];&#xD;
    data = Accumulate[Prepend[RandomVariate[mn, 1500], init]];&#xD;
    ListLinePlot[Transpose[data], &#xD;
     PlotLegends -&amp;gt; {&amp;#034;cds 1&amp;#034;, &amp;#034;cds 2&amp;#034;, &amp;#034;cds 3&amp;#034;, &amp;#034;cds 4&amp;#034;}, &#xD;
     PlotLabel -&amp;gt; Style[&amp;#034;CDS of observed series&amp;#034;, 15]]&#xD;
&#xD;
![enter image description here][2]&#xD;
&#xD;
    traindata = data[[;; 600]];&#xD;
    validata = data[[601 ;; 900]];&#xD;
    testdata = data[[901 ;;]];&#xD;
&#xD;
    trainset = &#xD;
      Table[Drop[traindata, None, -1][[i]] -&amp;gt; &#xD;
        Flatten[Take[traindata, All, -1]][[i]], {i, 1, Length[traindata]}];&#xD;
    testset = &#xD;
      Table[Drop[testdata, None, -1][[i]] -&amp;gt; &#xD;
        Flatten[Take[testdata, All, -1]][[i]], {i, 1, Length[testdata]}];&#xD;
    validset = &#xD;
      Table[Drop[validata, None, -1][[i]] -&amp;gt; &#xD;
        Flatten[Take[validata, All, -1]][[i]], {i, 1, Length[validata]}];&#xD;
&#xD;
    {ListLinePlot[Transpose[traindata], &#xD;
      PlotLegends -&amp;gt; {&amp;#034;cds 1&amp;#034;, &amp;#034;cds 2&amp;#034;, &amp;#034;cds 3&amp;#034;, &amp;#034;cds 4&amp;#034;}, &#xD;
      PlotLabel -&amp;gt; Style[&amp;#034;Training data&amp;#034;, 15]], &#xD;
     ListLinePlot[Transpose[testdata], &#xD;
      PlotLegends -&amp;gt; {&amp;#034;cds 1&amp;#034;, &amp;#034;cds 2&amp;#034;, &amp;#034;cds 3&amp;#034;, &amp;#034;cds 4&amp;#034;}, &#xD;
      PlotLabel -&amp;gt; Style[&amp;#034;Testing data&amp;#034;, 15]], &#xD;
     ListLinePlot[Transpose[validata], &#xD;
      PlotLegends -&amp;gt; {&amp;#034;cds 1&amp;#034;, &amp;#034;cds 2&amp;#034;, &amp;#034;cds 3&amp;#034;, &amp;#034;cds 4&amp;#034;}, &#xD;
      PlotLabel -&amp;gt; Style[&amp;#034;Validation data&amp;#034;, 15]]}&#xD;
&#xD;
![enter image description here][3]&#xD;
&#xD;
We can investigate the predictors separately by looking at histogram of the training data:&#xD;
&#xD;
    edata = Transpose[Drop[traindata, None, -1]];&#xD;
    {Histogram[edata[[1]], 20, ChartStyle -&amp;gt; &amp;#034;Pastel&amp;#034;, &#xD;
      PlotLabel -&amp;gt; &amp;#034;Feature 1&amp;#034;], &#xD;
     Histogram[edata[[2]], 20, ChartStyle -&amp;gt; &amp;#034;Rainbow&amp;#034;, &#xD;
      PlotLabel -&amp;gt; &amp;#034;Feature 2&amp;#034;], &#xD;
     Histogram[edata[[3]], 20, ChartStyle -&amp;gt; &amp;#034;NeonColors&amp;#034;, &#xD;
      PlotLabel -&amp;gt; &amp;#034;Feature 3&amp;#034;]}&#xD;
&#xD;
![enter image description here][4]&#xD;
&#xD;
#Setting the predictors#&#xD;
Having defined the training, testing and validation sets, we can now set up the prediction model:&#xD;
&#xD;
    Take[trainset, 10]&#xD;
&#xD;
&amp;gt; {{0.55, 0.72, 1.25} -&amp;gt; 1, {0.571876, 0.719578, 1.24021} -&amp;gt; &#xD;
  0.997824, {0.577651, 0.719425, 1.23595} -&amp;gt; &#xD;
  1.00456, {0.573492, 0.706407, 1.23029} -&amp;gt; &#xD;
  1.00455, {0.564589, 0.721109, 1.2309} -&amp;gt; &#xD;
  0.999223, {0.582398, 0.73248, 1.2497} -&amp;gt; &#xD;
  1.00538, {0.583999, 0.727467, 1.25179} -&amp;gt; &#xD;
  0.999114, {0.592003, 0.721993, 1.24155} -&amp;gt; &#xD;
  0.990911, {0.592474, 0.718474, 1.23417} -&amp;gt; &#xD;
  0.985031, {0.603327, 0.710775, 1.22836} -&amp;gt; 0.98689}&#xD;
&#xD;
Given the size of the training set we select **Random Forest** algorithm for prediction routine&#xD;
&#xD;
    pred = Predict[trainset, ValidationSet -&amp;gt; validset, Method -&amp;gt; &amp;#034;RandomForest&amp;#034;, PerformanceGoal -&amp;gt; &amp;#034;Quality&amp;#034;]&#xD;
![enter image description here][5]&#xD;
&#xD;
and obtain the information on the model&#xD;
&#xD;
    PredictorInformation[pred]&#xD;
&#xD;
![enter image description here][6]&#xD;
&#xD;
The automatic routine selects the Random Forest as the most optimal algorithm for this task&#xD;
&#xD;
##Conditional distribution##&#xD;
We can obtain the information about the distribution of the predicted value:&#xD;
&#xD;
    dist = pred[Drop[init, -1], &amp;#034;Distribution&amp;#034;]&#xD;
&#xD;
&amp;gt; NormalDistribution[1.00262, 0.0288765]&#xD;
&#xD;
It is confirmed that the predicted value is normally distributed with mean close to the  and low volatility.&#xD;
&#xD;
    PDF[dist, x]&#xD;
    Plot[PDF[dist, x], {x, 0.8, 1.25}, PlotStyle -&amp;gt; {Thick, Purple}, &#xD;
     FillingStyle -&amp;gt; LightGray, Filling -&amp;gt; Axis, &#xD;
     PlotLabel -&amp;gt; Style[&amp;#034;Conditional PDF of the predicted value&amp;#034;, 15]]&#xD;
&#xD;
&amp;gt; 13.8155 E^(-599.627 (-1.00262 + x)^2)&#xD;
&#xD;
![enter image description here][7]&#xD;
&#xD;
##Testing predictor accuracy##&#xD;
We may be interested to check how accurate the predictor works relative to the original data.&#xD;
&#xD;
    plotdata = Drop[traindata, None, -1];&#xD;
    adata = Transpose[Take[traindata, All, -1]] // Flatten;&#xD;
    pdata = Table[pred[plotdata[[i]]], {i, 1, Length[traindata]}];&#xD;
    ListLinePlot[{adata, pdata}, &#xD;
     PlotLabel -&amp;gt; Style[&amp;#034;Actual and Predicted data&amp;#034;, 15], &#xD;
     PlotLegends -&amp;gt; {&amp;#034;Actual&amp;#034;, &amp;#034;Predicted&amp;#034;}, PlotStyle -&amp;gt; {Blue, Red}]&#xD;
&#xD;
![enter image description here][8]&#xD;
&#xD;
We can see that the predictor replicates the original data quite well.&#xD;
&#xD;
##Verification with Testing data set##&#xD;
&#xD;
We can test and validate the classifier with the &amp;lt;ClassifierMeasurements&amp;gt; command. &#xD;
For example, we can used the testing set  defined above and look at its subset:&#xD;
&#xD;
    Take[testset, 10]&#xD;
&#xD;
&amp;gt; {{0.485579, 0.621485, 1.15959} -&amp;gt; &#xD;
&amp;gt; 1.0466, {0.485904, 0.630628, 1.15086} -&amp;gt; &#xD;
&amp;gt; 1.04336, {0.477018, 0.618847, 1.14833} -&amp;gt; &#xD;
&amp;gt; 1.04416, {0.492894, 0.627871, 1.15071} -&amp;gt; &#xD;
&amp;gt; 1.04294, {0.496431, 0.626622, 1.15025} -&amp;gt; &#xD;
&amp;gt; 1.04363, {0.501258, 0.629071, 1.14728} -&amp;gt; &#xD;
&amp;gt; 1.04505, {0.506147, 0.630316, 1.15071} -&amp;gt; &#xD;
&amp;gt; 1.05803, {0.492122, 0.627663, 1.15387} -&amp;gt; &#xD;
&amp;gt; 1.05949, {0.485113, 0.626491, 1.16395} -&amp;gt; &#xD;
&amp;gt; 1.0621, {0.476587, 0.632491, 1.16424} -&amp;gt; 1.05147}&#xD;
&#xD;
    pm = PredictorMeasurements[pred, testset]&#xD;
![enter image description here][9]&#xD;
&#xD;
The classifier returns the correct class group ping for all categories with high precision.&#xD;
&#xD;
 - Resting of residuals&#xD;
&#xD;
        pm[&amp;#034;ResidualPlot&amp;#034;]&#xD;
&#xD;
![enter image description here][10]&#xD;
&#xD;
 - Testing of comparison&#xD;
&#xD;
        pm[&amp;#034;ComparisonPlot&amp;#034;]&#xD;
![enter image description here][11]&#xD;
&#xD;
#Predictor sensitivity to the features variability#&#xD;
&#xD;
We look how the predictor reacts to the features input w.r.t. calibrated conditional distribution&#xD;
&#xD;
    {Plot[pred[{x, 0.7, 1.25}], {x, 0.4, 0.7}, PlotStyle -&amp;gt; Blue, &#xD;
      Filling -&amp;gt; Axis, FillingStyle -&amp;gt; LightYellow, &#xD;
      PlotLabel -&amp;gt; Style[&amp;#034;1st CDS sensiitivtiy&amp;#034;, 13]], &#xD;
     Plot[pred[{0.6, x, 1.25}], {x, 0.6, 0.8}, PlotStyle -&amp;gt; Magenta, &#xD;
      Filling -&amp;gt; Axis, FillingStyle -&amp;gt; LightGray, &#xD;
      PlotLabel -&amp;gt; Style[&amp;#034;2nd CDS sensiitivtiy&amp;#034;, 13]], &#xD;
     Plot[pred[{0.6, 0.7, x}], {x, 1.1, 1.3}, PlotStyle -&amp;gt; Green, &#xD;
      Filling -&amp;gt; Axis, FillingStyle -&amp;gt; LightBrown, &#xD;
      PlotLabel -&amp;gt; Style[&amp;#034;3rd CDS sensiitivtiy&amp;#034;, 13]]}&#xD;
![enter image description here][12]&#xD;
&#xD;
As charts above suggest, each feature affects the predictor differently:&#xD;
&#xD;
 - 1st CDS both decreases and increases the predicted value as the CDS&#xD;
   move upwards&#xD;
 - 2nd CDS increased the predicted value on the entire range, however    the degree of impact varies&#xD;
 - 3rd CDS is impact less on the lower side of the range and then increases the predicted CDS rate&#xD;
&#xD;
#Predicting outcomes with new data#&#xD;
&#xD;
We now apply the predictor to the out-of-sample data based on the specification above:&#xD;
&#xD;
 - Define new covariance matrix&#xD;
&#xD;
        tvols = {0.015, 0.02, 0.03};&#xD;
        tcorr = ({&#xD;
            {1, 0.4, 0.5},&#xD;
            {0.4, 1, 0.45},&#xD;
            {0.5, 0.45, 1}&#xD;
           });&#xD;
        tcm = Table[ tvols[[i]]*tvols[[j]]*tcorr[[i, j]], {i, 1, Length[tvols]}, {j, 1,  Length[tvols]}]&#xD;
&#xD;
&amp;gt; {{0.000225, 0.00012, 0.000225}, {0.00012, 0.0004, 0.00027}, {0.000225,&#xD;
   0.00027, 0.0009}}&#xD;
&#xD;
 - Generate the new CDS data for each feature&#xD;
&#xD;
        newinit = {0.68, 0.93, 1.4};&#xD;
        mn = MultinormalDistribution[{0, 0, 0}, tcm];&#xD;
        tdata = Accumulate[Prepend[RandomVariate[mn, 150], newinit]];&#xD;
        ListLinePlot[Transpose[tdata], &#xD;
         PlotLegends -&amp;gt; {&amp;#034;new cds 1&amp;#034;, &amp;#034;new cds 2&amp;#034;, &amp;#034;new cds 3&amp;#034;}, &#xD;
         PlotLabel -&amp;gt; Style[&amp;#034;Out-of-sample CDS data&amp;#034;, 15]]&#xD;
&#xD;
![enter image description here][13]&#xD;
&#xD;
    newdata = Table[predauto[tdata[[i]]], {i, 1, Length[tdata]}];&#xD;
    ListLinePlot[newdata, PlotTheme -&amp;gt; &amp;#034;Web&amp;#034;, &#xD;
     PlotLabel -&amp;gt; &#xD;
      Style[&amp;#034;Predicted value of CDS for put-of-sample input&amp;#034;, 15]]&#xD;
    ![enter image description here][14]&#xD;
&#xD;
We have obtained the new predicted data which we can investigate further:&#xD;
&#xD;
 - Data distribution&#xD;
&#xD;
        edist = SmoothKernelDistribution[newdata]&#xD;
![enter image description here][15]&#xD;
&#xD;
        Plot[PDF[edist, x], {x, 1, 1.3}, &#xD;
         PlotLabel -&amp;gt; &amp;#034;Probability density of the predicted value&amp;#034;, &#xD;
         Filling -&amp;gt; Axis, PlotRange -&amp;gt; All]&#xD;
![enter image description here][16]&#xD;
&#xD;
This is the estimated probability density from the predicted data.&#xD;
&#xD;
 - Descriptive statistics&#xD;
&#xD;
        stats = {Mean, Median, Variance, Min, Max, Skewness, Kurtosis};&#xD;
        TableForm[Through[stats[newdata]], TableHeadings -&amp;gt; {stats, None}]&#xD;
![enter image description here][17]&#xD;
&#xD;
 - Histogram&#xD;
&#xD;
        Histogram[newdata, 25, ChartStyle -&amp;gt; &amp;#034;Rainbow&amp;#034;]&#xD;
&#xD;
![enter image description here][18]&#xD;
&#xD;
#Alternative prediction methods#&#xD;
&#xD;
We can test other prediction methods available in Predict command:&#xD;
&#xD;
 - Linear regression&#xD;
&#xD;
        plinreg = &#xD;
         Predict[trainset, ValidationSet -&amp;gt; validset, &#xD;
          Method -&amp;gt; &amp;#034;LinearRegression&amp;#034;, PerformanceGoal -&amp;gt; &amp;#034;Quality&amp;#034;]&#xD;
![enter image description here][19]&#xD;
&#xD;
        pmlin = PredictorMeasurements[plinreg, testset];&#xD;
        pmlin[&amp;#034;ResidualPlot&amp;#034;]&#xD;
![enter image description here][20]&#xD;
&#xD;
        plinreg[Drop[init, -1], &amp;#034;Distribution&amp;#034;]&#xD;
&#xD;
&amp;gt; NormalDistribution[1.09925, 0.0769071]&#xD;
&#xD;
We observe higher predicted value and higher volatility relative to Random Forest&#xD;
&#xD;
 - NearestNeighbors&#xD;
&#xD;
        pnn = Predict[trainset, ValidationSet -&amp;gt; validset, &#xD;
          Method -&amp;gt; &amp;#034;NearestNeighbors&amp;#034;, PerformanceGoal -&amp;gt; &amp;#034;Quality&amp;#034;]&#xD;
![enter image description here][21]&#xD;
&#xD;
        pnntest = PredictorMeasurements[pnn, testset];&#xD;
        pnntest[&amp;#034;ResidualPlot&amp;#034;]&#xD;
&#xD;
![enter image description here][22]&#xD;
&#xD;
    pnn[Drop[init, -1], &amp;#034;Distribution&amp;#034;]&#xD;
&#xD;
&amp;gt; NormalDistribution[0.982606, 0.0304784]&#xD;
&#xD;
NearestNeighbors produces excellent fit to the data, but significantly higher volatility&#xD;
&#xD;
 - Neural network&#xD;
&#xD;
        pneural = &#xD;
         Predict[trainset, ValidationSet -&amp;gt; validset, &#xD;
          Method -&amp;gt; &amp;#034;NeuralNetwork&amp;#034;, PerformanceGoal -&amp;gt; &amp;#034;Quality&amp;#034;]&#xD;
![enter image description here][23]&#xD;
&#xD;
        pneuraltest = PredictorMeasurements[pneural, testset];&#xD;
        pneuraltest[&amp;#034;ResidualPlot&amp;#034;]&#xD;
&#xD;
![enter image description here][24]&#xD;
&#xD;
    pneural[Drop[init, -1], &amp;#034;Distribution&amp;#034;]&#xD;
&#xD;
&amp;gt; NormalDistribution[0.974001, 0.0461196]&#xD;
&#xD;
Reasonable fit to the data but with higher volatility than Random Forest.&#xD;
&#xD;
#Conclusion#&#xD;
Prediction is useful technique for finding relationship in data, especially if we have at our disposal larger set of data. Machine learning comes particularly handy in detecting patterns better than traditional linear model. The tools and methods such as decision trees, neutral networks or nearest neighborhood offer more flexibility to find complex relationship &#xD;
&#xD;
Prediction as a method to estimate outcome from supporting features naturally offers practical solutions to finance and economics where the estimation can be quite valuable. Market data generation, growth rates forecast, marketing campaign model testing or inflation prediction are just few examples where machine learning with prediction focus becomes essential tool for decision making.Richer contents and better prediction ability makes machine learning more powerful than traditional regression techniques.&#xD;
&#xD;
  [1]: /c/portal/getImageAttachment?filename=PredAnalimage.png&amp;amp;userId=387433&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=62621.png&amp;amp;userId=20103&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=108552.png&amp;amp;userId=20103&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=87493.png&amp;amp;userId=20103&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=90014.png&amp;amp;userId=20103&#xD;
  [6]: http://community.wolfram.com//c/portal/getImageAttachment?filename=36945.png&amp;amp;userId=20103&#xD;
  [7]: http://community.wolfram.com//c/portal/getImageAttachment?filename=56476.png&amp;amp;userId=20103&#xD;
  [8]: http://community.wolfram.com//c/portal/getImageAttachment?filename=61627.png&amp;amp;userId=20103&#xD;
  [9]: http://community.wolfram.com//c/portal/getImageAttachment?filename=75458.png&amp;amp;userId=20103&#xD;
  [10]: http://community.wolfram.com//c/portal/getImageAttachment?filename=82379.png&amp;amp;userId=20103&#xD;
  [11]: http://community.wolfram.com//c/portal/getImageAttachment?filename=323310.png&amp;amp;userId=20103&#xD;
  [12]: http://community.wolfram.com//c/portal/getImageAttachment?filename=841311.png&amp;amp;userId=20103&#xD;
  [13]: http://community.wolfram.com//c/portal/getImageAttachment?filename=241412.png&amp;amp;userId=20103&#xD;
  [14]: http://community.wolfram.com//c/portal/getImageAttachment?filename=725313.png&amp;amp;userId=20103&#xD;
  [15]: http://community.wolfram.com//c/portal/getImageAttachment?filename=603514.png&amp;amp;userId=20103&#xD;
  [16]: http://community.wolfram.com//c/portal/getImageAttachment?filename=998015.png&amp;amp;userId=20103&#xD;
  [17]: http://community.wolfram.com//c/portal/getImageAttachment?filename=880516.png&amp;amp;userId=20103&#xD;
  [18]: http://community.wolfram.com//c/portal/getImageAttachment?filename=523517.png&amp;amp;userId=20103&#xD;
  [19]: http://community.wolfram.com//c/portal/getImageAttachment?filename=414018.png&amp;amp;userId=20103&#xD;
  [20]: http://community.wolfram.com//c/portal/getImageAttachment?filename=497019.png&amp;amp;userId=20103&#xD;
  [21]: http://community.wolfram.com//c/portal/getImageAttachment?filename=189720.png&amp;amp;userId=20103&#xD;
  [22]: http://community.wolfram.com//c/portal/getImageAttachment?filename=458421.png&amp;amp;userId=20103&#xD;
  [23]: http://community.wolfram.com//c/portal/getImageAttachment?filename=741122.png&amp;amp;userId=20103&#xD;
  [24]: http://community.wolfram.com//c/portal/getImageAttachment?filename=756823.png&amp;amp;userId=20103</description>
    <dc:creator>Igor Hlivka</dc:creator>
    <dc:date>2015-04-16T00:08:17Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1341081">
    <title>UNET image segmentation in stem cells research</title>
    <link>https://community.wolfram.com/groups/-/m/t/1341081</link>
    <description>For my research project I had to encounter a thorny problem. But before I tell about the problem I would like to briefly mention something about my research project. Basically I am using embryonic stem cells that self-organize to form spheroids (balls of cells) to study gastrulation events. In order to not bog down the readers with technical jargon, gastrulation is a process where the stem cells start to form the different layers; each layer then goes onto form the various tissues/organs, in the process unraveling the developmental plan of the entire organism. I am using experimental techniques and quantitative principles from biophysics and engineering to understand some aspects of this crucial process&#xD;
&#xD;
Now coming back to the problem at hand, the gastruloids (image below) are quite rough in their appearance and not as beautiful as one would like them to be (only a mother can love such an image). Any means of quantifying these gastruloids requires me to initially segment them. When you see a time-lapse images of gastruloids it becomes apparent that they shed a lot of cells (for reasons I do not know yet). This adds considerable noise to the system; oftentimes to the point that  as a human  my eyes are fooled and run into the difficulty of finding the right contours for the spheroids. Here comes the disclosure: classical means/operations in image-processing (gradients and edge detection, filtering, morphological operations etc.. ) prove utterly futile for image segmentation in my case.&#xD;
&#xD;
![enter image description here][1]&#xD;
&#xD;
(A gastruloid  virtually a ball of cells with many shed around the periphery)&#xD;
&#xD;
So what can you do to address the problem where even the best image processing tool in existence   the human eyes  fails. This is precisely where you take help of neural networks. Neural networks are selling like hotcakes during the recent years and added life and hope to the once dead area of artificial intelligence. Again to avoid underlying technical details, neural networks is a paradigm utilized by the computer to mimic the working of a human brain by taking into account the complex interactions between the cells  but only digitally. There are many flavours of neural networks out there, each one geared towards performing a specific task. With advancements made in the area of deep learning/artificial intelligence, the neural nets have started to surpass humans in tasks that humans have been known to be best for i.e. classification tasks. A few recent examples that come to mind include Googles AlphaGo beating the former World Go champion and an AI diagnosing skin cancer with an unprecedented accuracy.&#xD;
&#xD;
I utilized one such flavour of neural networks (a deep convolutional network  termed as UNET) to solve my longstanding problem. I constructed the network in Wolfram-Language with external help from Alexey Golyshev. UNET is a deep convolutional network that has a series of convolutional and pooling operations in the contraction phase of the net (wherein the features are extracted) and a sequence of deconvolution &amp;amp; convolution operations in the expansion phase which then yields an output from the network. This output can be subjected to a threshold to ultimately generate a binarized mask (the image segmentation).&#xD;
&#xD;
![enter image description here][2]&#xD;
&#xD;
The architecture of UNET as provided by the author:  https://lmb.informatik.uni-freiburg.de/people/ronneber/u-net/&#xD;
&#xD;
    (* ::Package:: *)&#xD;
    BeginPackage[&amp;#034;UNETSegmentation`&amp;#034;]&#xD;
        &#xD;
    (* ::Section:: *)&#xD;
    (*Creating  UNet*)&#xD;
        &#xD;
    conv[n_]:=NetChain[&#xD;
    {&#xD;
     ConvolutionLayer[n,3,&amp;#034;PaddingSize&amp;#034;-&amp;gt;{1,1}],&#xD;
     Ramp,&#xD;
     BatchNormalizationLayer[],&#xD;
     ConvolutionLayer[n,3,&amp;#034;PaddingSize&amp;#034;-&amp;gt;{1,1}],&#xD;
     Ramp,&#xD;
     BatchNormalizationLayer[]&#xD;
    }&#xD;
    ];&#xD;
        &#xD;
    pool := PoolingLayer[{2,2},2];&#xD;
    &#xD;
    dec[n_]:=NetGraph[&#xD;
    {&#xD;
     &amp;#034;deconv&amp;#034; -&amp;gt; DeconvolutionLayer[n,{2,2},&amp;#034;Stride&amp;#034;-&amp;gt;{2,2}],&#xD;
     &amp;#034;cat&amp;#034; -&amp;gt; CatenateLayer[],&#xD;
     &amp;#034;conv&amp;#034; -&amp;gt; conv[n]&#xD;
    },&#xD;
    {&#xD;
     NetPort[&amp;#034;Input1&amp;#034;]-&amp;gt;&amp;#034;cat&amp;#034;,&#xD;
     NetPort[&amp;#034;Input2&amp;#034;]-&amp;gt;&amp;#034;deconv&amp;#034;-&amp;gt;&amp;#034;cat&amp;#034;-&amp;gt;&amp;#034;conv&amp;#034;&#xD;
    }&#xD;
    ];&#xD;
        &#xD;
    nodeGraphMXNET[net_,opt: (&amp;#034;MXNetNodeGraph&amp;#034;|&amp;#034;MXNetNodeGraphPlot&amp;#034;)]:= net~NetInformation~opt;&#xD;
        &#xD;
    UNET := NetGraph[&#xD;
    &amp;lt;|&#xD;
    &amp;#034;enc_1&amp;#034;-&amp;gt; conv[64],&#xD;
    &amp;#034;enc_2&amp;#034;-&amp;gt; {pool,conv[128]},&#xD;
    &amp;#034;enc_3&amp;#034;-&amp;gt; {pool,conv[256]},&#xD;
    &amp;#034;enc_4&amp;#034;-&amp;gt; {pool,conv[512]},&#xD;
    &amp;#034;enc_5&amp;#034;-&amp;gt; {pool,conv[1024]},&#xD;
    &amp;#034;dec_1&amp;#034;-&amp;gt; dec[512],&#xD;
    &amp;#034;dec_2&amp;#034;-&amp;gt; dec[256],&#xD;
    &amp;#034;dec_3&amp;#034;-&amp;gt; dec[128],&#xD;
    &amp;#034;dec_4&amp;#034;-&amp;gt; dec[64],&#xD;
    &amp;#034;map&amp;#034;-&amp;gt;{ConvolutionLayer[1,{1,1}],LogisticSigmoid}&#xD;
    |&amp;gt;,&#xD;
    {&#xD;
    NetPort[&amp;#034;Input&amp;#034;]-&amp;gt;&amp;#034;enc_1&amp;#034;-&amp;gt;&amp;#034;enc_2&amp;#034;-&amp;gt;&amp;#034;enc_3&amp;#034;-&amp;gt;&amp;#034;enc_4&amp;#034;-&amp;gt;&amp;#034;enc_5&amp;#034;,&#xD;
    {&amp;#034;enc_4&amp;#034;,&amp;#034;enc_5&amp;#034;}-&amp;gt;&amp;#034;dec_1&amp;#034;,&#xD;
    {&amp;#034;enc_3&amp;#034;,&amp;#034;dec_1&amp;#034;}-&amp;gt;&amp;#034;dec_2&amp;#034;,&#xD;
    {&amp;#034;enc_2&amp;#034;,&amp;#034;dec_2&amp;#034;}-&amp;gt;&amp;#034;dec_3&amp;#034;,&#xD;
    {&amp;#034;enc_1&amp;#034;,&amp;#034;dec_3&amp;#034;}-&amp;gt;&amp;#034;dec_4&amp;#034;,&#xD;
    &amp;#034;dec_4&amp;#034;-&amp;gt;&amp;#034;map&amp;#034;},&#xD;
    &amp;#034;Input&amp;#034;-&amp;gt;NetEncoder[{&amp;#034;Image&amp;#034;,{160,160},ColorSpace-&amp;gt;&amp;#034;Grayscale&amp;#034;}]&#xD;
    ]&#xD;
    &#xD;
    (* ::Section:: *)&#xD;
    (*DataPrep*)&#xD;
        &#xD;
    dataPrep[dirImage_,dirMask_]:=Module[{X, masks,imgfilenames, maskfilenames,ordering, fNames,func},&#xD;
    &#xD;
    func[dir_] := (SetDirectory[dir];&#xD;
    fNames = FileNames[];&#xD;
    ordering = Flatten@StringCases[fNames,x_~~p:DigitCharacter.. :&amp;gt; ToExpression@p];&#xD;
    Part[fNames,Ordering@ordering]);&#xD;
    &#xD;
    imgfilenames = func@dirImage;&#xD;
    X = ImageResize[Import[dirImage&amp;lt;&amp;gt;&amp;#034;\\&amp;#034;&amp;lt;&amp;gt;#],{160,160}]&amp;amp;/@imgfilenames;&#xD;
    maskfilenames = func@dirMask;&#xD;
    masks = Import[dirMask&amp;lt;&amp;gt;&amp;#034;\\&amp;#034;&amp;lt;&amp;gt;#]&amp;amp;/@maskfilenames;&#xD;
    {X, NetEncoder[{&amp;#034;Image&amp;#034;,{160,160},ColorSpace-&amp;gt;&amp;#034;Grayscale&amp;#034;}]/@masks}&#xD;
    ]&#xD;
    &#xD;
       &#xD;
    (* ::Section:: *)&#xD;
    (*Training UNet*)&#xD;
        &#xD;
    trainNetwithValidation[net_,dataset_,labeldataset_,validationset_,labelvalidationset_, batchsize_: 8, maxtrainRounds_: 100]:=Module[{},&#xD;
     SetDirectory[NotebookDirectory[]];&#xD;
     NetTrain[net, dataset-&amp;gt;labeldataset,All, ValidationSet -&amp;gt; Thread[validationset-&amp;gt; labelvalidationset],&#xD;
     BatchSize-&amp;gt;batchsize,MaxTrainingRounds-&amp;gt;maxtrainRounds, TargetDevice-&amp;gt;&amp;#034;GPU&amp;#034;,&#xD;
     TrainingProgressCheckpointing-&amp;gt;{&amp;#034;Directory&amp;#034;,&amp;#034;results&amp;#034;,&amp;#034;Interval&amp;#034;-&amp;gt;Quantity[5,&amp;#034;Rounds&amp;#034;]}]&#xD;
    ];&#xD;
        &#xD;
    trainNet[net_,dataset_,labeldataset_, batchsize_:8, maxtrainRounds_: 10]:=Module[{},&#xD;
     SetDirectory[NotebookDirectory[]];&#xD;
     NetTrain[net, dataset-&amp;gt;labeldataset,All,BatchSize-&amp;gt;batchsize,MaxTrainingRounds-&amp;gt;maxtrainRounds, TargetDevice-&amp;gt;&amp;#034;GPU&amp;#034;,&#xD;
     TrainingProgressCheckpointing-&amp;gt;{&amp;#034;Directory&amp;#034;,&amp;#034;results&amp;#034;,&amp;#034;Interval&amp;#034;-&amp;gt; Quantity[5,&amp;#034;Rounds&amp;#034;]}]&#xD;
    ];&#xD;
        &#xD;
    (* ::Section:: *)&#xD;
    (*Measure Accuracy*)&#xD;
        &#xD;
    measureModelAccuracy[net_,data_,groundTruth_]:= Module[{acc},&#xD;
    acc =Table[{i, 1.0 - HammingDistance[N@Round@Flatten@net[data[[i]],TargetDevice-&amp;gt;&amp;#034;GPU&amp;#034;],&#xD;
     Flatten@groundTruth[[i]]]/(160*160)},{i,Length@data}&#xD;
    ];&#xD;
    {Mean@Part[acc,All,2],TableForm@acc}&#xD;
    ];&#xD;
        &#xD;
    (* ::Section:: *)&#xD;
    (*Miscellaneous*)&#xD;
    &#xD;
    saveNeuralNet[net_]:= Module[{dir = NotebookDirectory[]},&#xD;
     Export[dir&amp;lt;&amp;gt;&amp;#034;unet.wlnet&amp;#034;,net]]/; Head[net]=== NetGraph;&#xD;
    &#xD;
    &#xD;
    saveInputs[data_,labels_,opt:(&amp;#034;data&amp;#034;|&amp;#034;validation&amp;#034;)]:=Module[{},&#xD;
     SetDirectory[NotebookDirectory[]];&#xD;
     Switch[opt,&amp;#034;data&amp;#034;,&#xD;
      Export[&amp;#034;X.mx&amp;#034;,data];Export[&amp;#034;Y.mx&amp;#034;,labels],&#xD;
      &amp;#034;validation&amp;#034;,&#xD;
      Export[&amp;#034;Xval.mx&amp;#034;,data];Export[&amp;#034;Yval.mx&amp;#034;,labels]&#xD;
     ]&#xD;
    ]&#xD;
        &#xD;
    EndPackage[];&#xD;
&#xD;
The above code can also be found in the repository @ [Wolfram-MXNET GITHUB][3]&#xD;
&#xD;
I trained my network over my laptop GPU (Nvidia GTX 1050) by feeding an augmented data (a set of 300 images constructed from a small dataset) . The training was done in under 3 minutes !. The accuracy (computed as the Hamming Distance between two vectors) of the generated binary masks with respect to the ground truth (unseen data) for a set of 90 images was 98.55 %. And with this a task that previously required me to painstakingly trace the contour of the gastruloids manually can now be performed in a matter of milliseconds. All the saved time and perspiration to be utilized somewhere else?&#xD;
&#xD;
![enter image description here][4]&#xD;
&#xD;
Below is the results obtained by applying our trained net on one input:&#xD;
&#xD;
![enter image description here][5]&#xD;
&#xD;
The interesting aspect for me regarding the network was that despite my gastruloids being highly dynamic (changing shape over time) I never had to explicity state it to the network. All the necessary features were learned from the limited number of images that I trained my network with. This is the beauty of the neural network.&#xD;
&#xD;
![enter image description here][6]&#xD;
&#xD;
Finally the output of the net as applied on a number of unseen images:&#xD;
&#xD;
![enter image description here][7]&#xD;
&#xD;
Note: I have a python MXNET version of UNET  @  [python mxnet GITHUB][8]&#xD;
&#xD;
The wolfram version of UNET however seems to outperform the python version even though it also utilizes MXNET at the back-end for implementing neural networks. It should not come as a surprise because my guess is that the people at Wolfram Research may have done internal optimizations on top of the library&#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=gastruloid.png&amp;amp;userId=942204&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=u-net-architecture-initial-authors-implementation.png&amp;amp;userId=942204&#xD;
  [3]: https://github.com/alihashmiii/UNet-Segmentation-Wolfram&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=img1.png&amp;amp;userId=942204&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=img2.png&amp;amp;userId=942204&#xD;
  [6]: http://community.wolfram.com//c/portal/getImageAttachment?filename=img3.png&amp;amp;userId=942204&#xD;
  [7]: http://community.wolfram.com//c/portal/getImageAttachment?filename=img4.png&amp;amp;userId=942204&#xD;
  [8]: https://github.com/alihashmiii/blobsegmentation</description>
    <dc:creator>Ali Hashmi</dc:creator>
    <dc:date>2018-05-17T15:06:45Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/970999">
    <title>Market Sentiment Analysis</title>
    <link>https://community.wolfram.com/groups/-/m/t/970999</link>
    <description>Text and sentiment analysis has become a very popular topic in quantitative research over the last decade, with applications ranging from market research and political science, to e-commerce.  In this post I am going to outline an approach to the subject, together with some core techniques, that have applications in investment strategy.&#xD;
&#xD;
In the early days of the developing field of market sentiment analysis, the supply of machine readable content was limited mainly to mainstream providers of financial news such as Reuters or Bloomberg. Over time this has changed with the entry of new competitors in the provision of machine readable news, including, for example, Ravenpack or more recent arrivals like Accern.  Providers often seek to sell not only the raw news feed service, but also their own proprietary sentiment indicators that are claimed to provide additional insight into how individual stocks, market sectors, or the overall market are likely to react to news.  There is now what appears to be a cottage industry producing white papers seeking to demonstrate the value of these services, often accompanied by some impressive pro-forma performance statistics for the accompanying strategies, which include long-only, long/short, market neutral and statistical arbitrage.&#xD;
&#xD;
For the purpose of demonstration I intend to forego the blandishments of these services, although many are no doubt are excellent, since the reader is perhaps unlikely to have access to them.  Instead, in what follows I will focus on a single news source, albeit a highly regarded one:  the Wall Street Journal.  This is, of course, a simplification intended for illustrative purposes only  in practice one would need to use a wide variety of news sources and perhaps subscribe to a machine readable news feed service.  But similar principles and techniques can be applied to any number of news feeds or online sites.&#xD;
&#xD;
**The WSJ News Archive**&#xD;
&#xD;
We are going to access the Journals online archive, which presents daily news items in a convenient summary format, an example of which is shown below. The archive runs from the beginning of 2012 through to the current day, providing ample data for analysis.  In what follows, I am going to make a few important assumptions, neither of which is likely to be 100% accurate  but which will not detract too much from the validity of the research, I hope.  The first assumption is that the news items shown in each daily archive were reported prior to the market open at 9:30 AM.  This is likely to be true for the great majority of the stories, but there are no doubt important exceptions.  Since we intend to treat the news content of each archive as antecedent to the market action during the corresponding trading session, exceptions are likely to introduce an element of look-ahead bias.  The second assumption is that the archive for each day is shown in the form in which it would have appeared on the day in question.  In reality, there are likely to have been revisions to some of the stores made subsequent to their initial publication. So, here too, we must allow for the possibility of look-ahead bias in the ensuing analysis.&#xD;
&#xD;
![enter image description here][1]&#xD;
&#xD;
With those caveats out of the way, lets proceed.  We are going to be using broad market data for the S&amp;amp;P 500 index in the analysis to follow, so the first step is to download daily price series for the index.  Note that we begin with daily opening prices, since we intend to illustrate the application of news sentiment analysis with a theoretical day-trading strategy that takes positions at the start of each trading session, exiting at market close.&#xD;
&#xD;
![enter image description here][2]&#xD;
&#xD;
From there we calculate the intraday return in the index, from market open to close, as follows:&#xD;
&#xD;
![enter image description here][3]&#xD;
&#xD;
**Text Analysis &amp;amp; Classification**&#xD;
&#xD;
Next we turn to the task of reading the news archive and categorizing its content.  Mathematica makes the importation of html pages very straightforward,  and we can easily crop the raw text string to exclude page headers and footers.  The approach I am going to take is to derive a sentiment indicator based on an analysis of the sentiment of each word in the daily archive.  Before we can do that we must first convert the text into individuals words, stripping out standard stop-words such as &amp;#034;the&amp;#034; and &amp;#034;in&amp;#034; and converting all the text to lower case.  Naturally one can take this pre-processing a great deal further, by identifying and separating out proper nouns, for example.  Once the text processing stage is complete we can quickly summarize the content, for example by looking at the most common words, or by representing the entire archive in the form of a word cloud.  Given that we are using the archive for the first business day of 2012, it is perhaps unsurprising that we find that &amp;#034;2012&amp;#034;, &amp;#034;new&amp;#034; and &amp;#034;year&amp;#034; feature so prominently!&#xD;
&#xD;
    archive = &#xD;
      Import[StringJoin[&amp;#034;http://www.wsj.com/public/page/archive-&amp;#034;, &#xD;
        DateString[&#xD;
         datelist[[1]], {&amp;#034;Year&amp;#034;, &amp;#034;-&amp;#034;, &amp;#034;MonthShort&amp;#034;, &amp;#034;-&amp;#034;, &amp;#034;DayShort&amp;#034;}], &#xD;
        &amp;#034;.html&amp;#034;]];&#xD;
    archive = &#xD;
      StringDrop[archive, &#xD;
       StringPosition[archive, &#xD;
         DateString[&#xD;
          datelist[[1]], {&amp;#034;MonthName&amp;#034;, &amp;#034; &amp;#034;, &amp;#034;DayShort&amp;#034;, &amp;#034;, &amp;#034;, &#xD;
           &amp;#034;Year&amp;#034;}]][[1, 2]]];&#xD;
    archive = &#xD;
      StringTake[&#xD;
       archive, -1 + StringPosition[archive, &amp;#034;ARCHIVE FILTER&amp;#034;][[1, 1]]];&#xD;
    archivewords = ToLowerCase[DeleteStopwords[TextWords[archive]]];&#xD;
    TakeLargest[Counts[archivewords], 20]&#xD;
    WordCloud[archivewords]&#xD;
&#xD;
&amp;lt;|&amp;#034;2012&amp;#034; -&amp;gt; 45, &amp;#034;new&amp;#034; -&amp;gt; 41, &amp;#034;year&amp;#034; -&amp;gt; 39, &amp;#034;u.s.&amp;#034; -&amp;gt; 33, &amp;#034;2011&amp;#034; -&amp;gt; 21,&#xD;
  &amp;#034;asia&amp;#034; -&amp;gt; 16, &amp;#034;iowa&amp;#034; -&amp;gt; 16, &amp;#034;crisis&amp;#034; -&amp;gt; 15, &amp;#034;biggest&amp;#034; -&amp;gt; 14, &#xD;
 &amp;#034;news&amp;#034; -&amp;gt; 14, &amp;#034;markets&amp;#034; -&amp;gt; 14, &amp;#034;india&amp;#034; -&amp;gt; 13, &amp;#034;said&amp;#034; -&amp;gt; 13, &#xD;
 &amp;#034;economic&amp;#034; -&amp;gt; 13, &amp;#034;market&amp;#034; -&amp;gt; 13, &amp;#034;oil&amp;#034; -&amp;gt; 13, &amp;#034;europe&amp;#039;s&amp;#034; -&amp;gt; 13, &#xD;
 &amp;#034;look&amp;#034; -&amp;gt; 12, &amp;#034;day&amp;#034; -&amp;gt; 12, &amp;#034;price&amp;#034; -&amp;gt; 12|&amp;gt;&#xD;
&#xD;
![enter image description here][4]&#xD;
&#xD;
The subject of sentiment analysis is a complex one and I only touch on it here.  For those interested in the subject I can recommend The Text Mining Handbook, by Feldman and Sanger, which is a standard work on the topic.  Here I am going to employ a machine learning classifier provided with Mathematica 11.  It is not terribly sophisticated (or, at least, has not been developed with financial applications especially in mind), but will serve for the purposes of this article.  For those unfamiliar with the functionality, the operation of the sentiment classification algorithm is straightforward enough.  For instance:&#xD;
&#xD;
![enter image description here][5]&#xD;
&#xD;
We apply the algorithm to classify each word in the daily news archive and arrive at a sentiment indicator based on the proportion of words that are classified as &amp;#034;positive&amp;#034;.  The sentiment reading for the archive for Jan-3, 2012, for example, turns out to be 67.4%:&#xD;
&#xD;
![enter image description here][6]&#xD;
&#xD;
**Sentiment Index Analytics**&#xD;
&#xD;
We can automate the process of classifying the entire WSJ archive with just a few lines of code, producing a time series for the daily sentiment indicator, which has an average daily value of  68.5%  - the WSJ crowd tends to be bullish, clearly!  Note how the 60-day moving average of the indicator rises steadily over the period from 2012 through Q1 2015, then abruptly reverses direction, declining steadily thereafter - even somewhat precipitously towards the end of 2016.&#xD;
&#xD;
    WSJSentimentIndicator[date_] := &#xD;
     Module[{d = date, archive, archivewords, WSJSI}, &#xD;
      archive = &#xD;
       Import[StringJoin[&amp;#034;http://www.wsj.com/public/page/archive-&amp;#034;, &#xD;
         DateString[d, {&amp;#034;Year&amp;#034;, &amp;#034;-&amp;#034;, &amp;#034;MonthShort&amp;#034;, &amp;#034;-&amp;#034;, &amp;#034;DayShort&amp;#034;}], &#xD;
         &amp;#034;.html&amp;#034;]];&#xD;
      archive = &#xD;
       StringDrop[archive, &#xD;
        StringPosition[archive, &#xD;
          DateString[d, {&amp;#034;MonthName&amp;#034;, &amp;#034; &amp;#034;, &amp;#034;DayShort&amp;#034;, &amp;#034;, &amp;#034;, &amp;#034;Year&amp;#034;}]][[1,&#xD;
          2]]];&#xD;
      archive = &#xD;
       StringTake[&#xD;
        archive, -1 + StringPosition[archive, &amp;#034;ARCHIVE FILTER&amp;#034;][[1, 1]]];&#xD;
      archivewords = ToLowerCase[DeleteStopwords[TextWords[archive]]];&#xD;
      WSJSI = #Positive/(#Negative + #Positive) &amp;amp;@&#xD;
         Counts[Classify[&amp;#034;Sentiment&amp;#034;, archivewords]] // N;&#xD;
      {WSJSI, archivewords, archive}]&#xD;
&#xD;
![enter image description here][7]&#xD;
&#xD;
As with most data series in investment research, we are less interested in the level of a variable, such as a stock price, than we are in the changes in level.   So the next step is to calculate the daily percentage change in the sentiment indicator and examine the correlation with the corresponding intraday return in the S&amp;amp;P 500 Index.  At first glance our sentiment indicator appears to have very little predictive power  - the correlation between indicator changes and market returns is negligibly small overall - but we shall later see that this is not the last word.&#xD;
&#xD;
![enter image description here][8]&#xD;
&#xD;
**Conditional Distributions**&#xD;
&#xD;
Thus far the results appear discouraging; but as is often the case with this type of analysis we need to look more closely at the conditional distribution of returns.  Specifically, we will examine the conditional distribution of S&amp;amp;P 500 Index returns when changes in the sentiment index are in the upper and lower quantiles of the distribution. This will enable us to isolate the impact of changes in market sentiment at times when the swings in sentiment are strongest.  In the analysis below, we begin by examining the upper and lower third of the distribution of changes in sentiment:&#xD;
&#xD;
![enter image description here][9]&#xD;
&#xD;
The analysis makes clear that the distribution of S&amp;amp;P 500 Index returns is very different on days when the change in market sentiment is large and positive vs. large and negative. The difference is not just limited to the first moment of the conditional distribution, where the difference in the mean return is large and statistically significant, but also in the third moment.  The much larger, negative skewness means that there is a greater likelihood of a large decline in the market on days in which there is a sizable drop in market sentiment, than on days in which sentiment significantly improves.  In other words, the influence of market sentiment changes is manifest chiefly through the mean and skewness of the conditional distributions of market returns.&#xD;
&#xD;
**A News Trading Algorithm**&#xD;
&#xD;
We can capitalize on these effects using a simple trading strategy in which we increase the capital allocated to a long-SPX position on days when market sentiment improves, while reducing exposure on days when market sentiment falls.  We increase the allocation by a factor - designated the leverage factor - on days when the change in the sentiment indicator is in the upper 1/3 of the distribution, while reducing the allocation by 1/leveragefactor on days when the change in the sentiment indicator falls in lower 1/3 of the distribution.  The allocation on other days is 100%.  The analysis runs as follows:&#xD;
&#xD;
    period = QuantityMagnitude@&#xD;
       DateDifference[First@datelist, Last@datelist, &amp;#034;Year&amp;#034;];&#xD;
    AnnStd = Sqrt[252]*&#xD;
       StandardDeviation[&#xD;
        Transpose@{tsSPXreturns[&amp;#034;Values&amp;#034;], strategyreturns}];&#xD;
    cf = {tsVTDSPX[Last@datelist]/1000 - 1, &#xD;
       tsVTDstrategy[Last@datelist]/1000 - 1};&#xD;
    CAGR = -1 + (1 + cf)^(1/period);&#xD;
    IR = CAGR/AnnStd;&#xD;
&#xD;
    Print[Style[&amp;#034;News Sentiment Strategy&amp;#034;, &amp;#034;Subsection&amp;#034;]];&#xD;
    P1 = Style[&#xD;
       NumberForm[&#xD;
        TableForm[{CAGR, AnnStd, IR}, &#xD;
         TableHeadings -&amp;gt; {{&amp;#034;CAGR&amp;#034;, &amp;#034;Ann. StDev.&amp;#034;, &#xD;
            &amp;#034;IR&amp;#034;}, {Style[&amp;#034;SP500 Index&amp;#034;, Bold], &#xD;
            Style[&amp;#034;Strategy&amp;#034;, Bold]}}], {6, 2}], FontSize -&amp;gt; 14];&#xD;
    P2 = DateListPlot[{tsVTDSPX, tsVTDstrategy}, Filling -&amp;gt; Axis, &#xD;
       PlotLegends -&amp;gt; {&amp;#034;S&amp;amp;P500 Index&amp;#034;, &amp;#034;Strategy&amp;#034;}, &#xD;
       PlotLabel -&amp;gt; Style[&amp;#034;Value of $1,000&amp;#034;, Bold], ImageSize -&amp;gt; Medium];&#xD;
    Print[P1];&#xD;
    Print[P2];&#xD;
&#xD;
![enter image description here][10]&#xD;
&#xD;
&#xD;
It turns out that, using a leverage factor of 2.0, we can increase the CAGR from 10% to 21% over the period from 2012-2016 using the conditional distribution approach.  This performance enhancement comes at a cost, since the annual volatility of the news sentiment strategy is 17% compared to only 12% for the long-only strategy. However, the overall net result is positive, since the risk-adjusted rate of return increases from 0.82 to 1.28.&#xD;
&#xD;
We can explore the robustness of the result, comparing different quantile selections and leverage factors using Mathematica&amp;#039;s interactive Manipulate function:&#xD;
&#xD;
    Manipulate[&#xD;
     percentiles = &#xD;
      Quantile[tsSIchange, {quantilefrac, 1 - quantilefrac}];&#xD;
     bottompercentile = &#xD;
      Flatten[Position[tsSIchange[&amp;#034;Values&amp;#034;], &#xD;
        x_ /; x &amp;lt; percentiles[[1]]]];&#xD;
     toppercentile = &#xD;
      Flatten[Position[tsSIchange[&amp;#034;Values&amp;#034;], &#xD;
        x_ /; x &amp;gt; percentiles[[2]]]];&#xD;
     strategyreturns = tsSPXreturns[&amp;#034;Values&amp;#034;];&#xD;
     strategyreturns[[bottompercentile]] = (1/leveragefactor)*&#xD;
       strategyreturns[[bottompercentile]];&#xD;
     strategyreturns[[toppercentile]] = &#xD;
      leveragefactor*strategyreturns[[toppercentile]];&#xD;
     tsVTDstrategy = &#xD;
      TimeSeries[&#xD;
       Transpose[{datelist, &#xD;
         1000*FoldList[Times, 1, 1 + strategyreturns]}]];&#xD;
     DateListPlot[{tsVTDSPX, tsVTDstrategy}, Filling -&amp;gt; Axis, &#xD;
      PlotLegends -&amp;gt; {&amp;#034;S&amp;amp;P500 Index&amp;#034;, &amp;#034;Strategy&amp;#034;}, &#xD;
      PlotLabel -&amp;gt; Style[&amp;#034;Value of $1,000&amp;#034;, Bold], &#xD;
      ImageSize -&amp;gt; Medium], {leveragefactor, 1, 3}, {quantilefrac, 0.1, &#xD;
      0.5}]&#xD;
&#xD;
![enter image description here][11]&#xD;
&#xD;
**Conclusion**&#xD;
&#xD;
A simple market sentiment indicator can be created quite easily from publicly available news archives, using a standard machine learning sentiment classification algorithm.  A market sentiment algorithm constructed using methods as straightforward as this appears to provide the capability to differentiate the conditional distribution of market returns on days when changes in market sentiment are significantly positive or negative.  The differences in the higher moments of the conditional distribution appears to be as significant as the differences in the mean.  In principle, we can use the insight provided by the sentiment indicator to enhance a long-only day-trading strategy, increasing leverage and allocation on days when changes to market sentiment are positive and reducing them on days when sentiment declines.  The performance enhancements resulting from this approach appear to be significant.&#xD;
&#xD;
Several caveats apply.  The S&amp;amp;P 500 index is not tradable, of course, and it is not uncommon to find trading strategies that produce interesting theoretical results.  In practice one would be obliged to implement the strategy using a tradable market proxy, such as a broad market ETF or futures contract.  The strategy described here, which enters and exits positions daily, would incur substantial trading costs, that would be further exacerbated by the use of leverage.&#xD;
&#xD;
Of course there are many other uses one can make of news data, in particular with firm-specific news and sentiment analytics, that fall outside the scope of this article.  Hopefully, however, the methodology described here will provide a sign-post towards further, more practically useful research.&#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fig1.png&amp;amp;userId=773999&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fig2.png&amp;amp;userId=773999&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fig3.png&amp;amp;userId=773999&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fig4a.png&amp;amp;userId=773999&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fig5.png&amp;amp;userId=773999&#xD;
  [6]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fig6.png&amp;amp;userId=773999&#xD;
  [7]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fig8.png&amp;amp;userId=773999&#xD;
  [8]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fig9.png&amp;amp;userId=773999&#xD;
  [9]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fig10.png&amp;amp;userId=773999&#xD;
  [10]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fig10a.png&amp;amp;userId=773999&#xD;
  [11]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fig15.png&amp;amp;userId=773999</description>
    <dc:creator>Jonathan Kinlay</dc:creator>
    <dc:date>2016-11-28T20:41:07Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1646303">
    <title>UNET: neural network for 2D &amp;amp; 3D image segmentation w/ medical examples</title>
    <link>https://community.wolfram.com/groups/-/m/t/1646303</link>
    <description># UNET [![DOI](https://zenodo.org/badge/137186334.svg)](https://zenodo.org/badge/latestdoi/137186334) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/dwyl/esta/issues)&#xD;
&#xD;
&#xD;
----------&#xD;
&#xD;
![Automated 3D muscle segmentation using UNET / RESNET using DIXON MRI data][17]&#xD;
&#xD;
&#xD;
A package to generate and train a UNET deep convolutional network for 2D and 3D image segmentation.&#xD;
&#xD;
Some code was based on [work][1] by [@Ali Hashmi][at0], which was also dicussed in [this post][2] &#xD;
The full version of the toolbox can be found on my [github page][3].&#xD;
&#xD;
* [Information](#information)&#xD;
* [Install toolbox](#install-toolbox)&#xD;
* [Using the toolbox](#using-the-toolbox)&#xD;
* [Functionality](#functionality)&#xD;
* [Visualization](#visualization)&#xD;
* [Example](#example)&#xD;
&#xD;
## Information&#xD;
&#xD;
UNET is developed for [Mathematica](https://www.wolfram.com/mathematica/).&#xD;
It contains the following toolboxes:&#xD;
&#xD;
- UnetCore&#xD;
- UnetSupport&#xD;
&#xD;
Documentation of all functions and their options is fully integrated in the Mathematica documentation.&#xD;
The toolbox always works within the latest version of Mathematica and does not support any backward compatibility.&#xD;
&#xD;
All code and documentation is maintained and uploaded to github using [Workbench](https://www.wolfram.com/workbench/).&#xD;
&#xD;
## Install toolbox&#xD;
&#xD;
Install the toolbox in the Mathematica UserBaseDirectory &amp;gt; Applications.&#xD;
&#xD;
	FileNameJoin[{$UserBaseDirectory, &amp;#034;Applications&amp;#034;}]&#xD;
  &#xD;
## Using the toolbox&#xD;
&#xD;
The toolbox can be loaded by using &amp;lt;&amp;lt;UNET`&#xD;
&#xD;
The notbook ``UNET.nb`` shows examples of how to use the toolbox on artificially generated 2D data. &#xD;
There are also examples how to visualize the layer of your trained network and how to visualize the training itself. &#xD;
&#xD;
## Functionality&#xD;
&#xD;
The network supports multi channel inputs and multi class segmentation.&#xD;
&#xD;
* UNET generates a UNET convolutional network.  &#xD;
    * 2D UNET  &#xD;
![UNET 2D][4]&#xD;
    * 3D UNET  &#xD;
![UNET 3D][5]&#xD;
&#xD;
* Loss Layers: Training the data is done using three loss layers: a SoftDiceLossLayer, BrierLossLayer and a CrossEntropyLossLayer.  &#xD;
![SoftDiceLossLayer, BrierLossLayer and a CrossEntropyLossLayer][6]&#xD;
&#xD;
* Convolution Blocks: The toobox contains five different convolution blocks that build up the network: [UNET][7], UResNet, [RestNet][8], UDenseNet, [DensNet][9].  &#xD;
![Convolution blocks][10]&#xD;
&#xD;
* SplitTrainData splits the data and labels into training, validation and test data.  &#xD;
![split train Data][11]&#xD;
&#xD;
* TrainUNET trains the network.  &#xD;
![Train UNET][12]&#xD;
&#xD;
## Visualization&#xD;
&#xD;
* Visualize the network and results.  &#xD;
    * Visualize the features of the layers.  &#xD;
![Visualize layer features][13]&#xD;
    * Visualize the results.  &#xD;
![Visualize the results][14]&#xD;
    * Animate the training process.  &#xD;
![UNET 2D animation][15]  &#xD;
![UNET 3D animation][16]&#xD;
&#xD;
## Example&#xD;
&#xD;
* Example: 3D segmentation of lower legg muscles using MRI data.  &#xD;
&#xD;
![Automated 3D muscle segmentation using UNET / RESNET using DIXON MRI data][17]&#xD;
&#xD;
&#xD;
  [1]: https://github.com/alihashmiii/UNet-Segmentation-Wolfram&#xD;
  [2]: https://community.wolfram.com/groups/-/m/t/1341081?p_p_auth=w8PIeeiA&#xD;
  [3]: https://github.com/mfroeling&#xD;
  [4]: https://community.wolfram.com//c/portal/getImageAttachment?filename=UNET2D.PNG&amp;amp;userId=1332602&#xD;
  [5]: https://community.wolfram.com//c/portal/getImageAttachment?filename=UNET3D.PNG&amp;amp;userId=1332602&#xD;
  [6]: https://community.wolfram.com//c/portal/getImageAttachment?filename=Loss.PNG&amp;amp;userId=1332602&#xD;
  [7]: https://arxiv.org/abs/1505.04597&#xD;
  [8]: https://arxiv.org/abs/1512.03385&#xD;
  [9]: https://arxiv.org/abs/1608.06993&#xD;
  [10]: https://community.wolfram.com//c/portal/getImageAttachment?filename=convblocks.PNG&amp;amp;userId=1332602&#xD;
  [11]: https://community.wolfram.com//c/portal/getImageAttachment?filename=Split.PNG&amp;amp;userId=1332602&#xD;
  [12]: https://community.wolfram.com//c/portal/getImageAttachment?filename=Train.PNG&amp;amp;userId=1332602&#xD;
  [13]: https://community.wolfram.com//c/portal/getImageAttachment?filename=Visualize1.PNG&amp;amp;userId=1332602&#xD;
  [14]: https://community.wolfram.com//c/portal/getImageAttachment?filename=Visualize2.PNG&amp;amp;userId=1332602&#xD;
  [15]: https://community.wolfram.com//c/portal/getImageAttachment?filename=amin0-v2.gif&amp;amp;userId=1332602&#xD;
  [16]: https://community.wolfram.com//c/portal/getImageAttachment?filename=amin4-v2.gif&amp;amp;userId=1332602&#xD;
  [17]: https://community.wolfram.com//c/portal/getImageAttachment?filename=Muscle_Segmentation.jpg&amp;amp;userId=1332602&#xD;
&#xD;
 [at0]: https://community.wolfram.com/web/alihashmi87</description>
    <dc:creator>Martijn Froeling</dc:creator>
    <dc:date>2019-04-03T20:01:26Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/465774">
    <title>Machine Learning in Finance with Classification approach</title>
    <link>https://community.wolfram.com/groups/-/m/t/465774</link>
    <description># Abstract&#xD;
&#xD;
We discuss classification as the data-mining technique in patterns recognition and supervised machine-learning. Comparison of classification to other data exploration methods is presented and the importance of this approach is further discussed. We demonstrate the machine-learning method in finance and show how credit risk categorisation can be easily achieved with classification technique.&#xD;
&#xD;
![Classification][1]&#xD;
&#xD;
# Introduction&#xD;
&#xD;
Searching for patterns in economic and financial data has a long history. One of the oldest approached explored by econometricians was the data arrangement into groups based on their similarities and differences. As computer resources improved there was a growth in the scope and availability of new computational methods. However, the greatest data analysis challenges are undoubtedly more recent. Advances in observational and collection methods have generated, and continue to generate enormous volumes of information that present significant storage, retrieval and analysis challenges. &#xD;
&#xD;
The analytical tools that extract information from data can be placed into two broad and overlapping categories: (i) **cluster** and (ii) **classification** methods. Using these techniques, datasets can be classified according to a specific property by measurements indirectly related to the property of interest. An empirical relationship on the classification rule can be developed from a dataset for which the property of interest and the measurements are known. The classification rule can then be used to predict the property in samples that are not part of the original set.&#xD;
&#xD;
In view of the above, we view classification as a data-mining technique that comes particularly helpful in **finding patterns** in the data that can dramatically reduce its dimensionality. It helps identifying class membership from prediction variables and identify features that either contribute or can be used to predict class membership.&#xD;
&#xD;
# Machine learning&#xD;
&#xD;
Machine learning is a subset of artificial intelligence that incorporates a large number of statistical ideas and methods and uses algorithms&#xD;
that &amp;#039;learn&amp;#039; from data. Learning is based around finding the relationship  between a set of features in the data structure. **Induction** and **deduction** are two types of reasoning used in the learning process. Induction stems from the particular to the general and can be used to generate classification rules from examples by establishing &amp;#039;cause-effect&amp;#039; relationships between existing facts. Deduction, on the other hand, is concerned with reasoning using existing knowledge. The requirement for previously acquired knowledge is one of the main differences between deduction and induction. Because deduction can be used to predict the consequences of events or to determine the prerequisite conditions for an observed event, it is at the heart of most expert systems.&#xD;
&#xD;
Machine learning is primarily based on induction. Whilst this is natural consequence of the method itself, it leads to paternally two problems:&#xD;
&#xD;
- Learning by induction requires potentially many examples to &amp;#039;acquire knowledge&amp;#039;&#xD;
&#xD;
- It is not guaranteed to be &amp;#039;future-proof&amp;#039; since the main principle is based on what happened in the past&#xD;
&#xD;
These difficulties are not restricted to machine learning. it is well known that relationships models based on regression should not be extrapolated beyond the limits of the original data. A good news, however, is that noise does not have consistent effects on machine learning algorithms; for example, neural networks, and instance-based methods all use &amp;#039;distributed&amp;#039; representations  This is important because distributed representations should be less susceptible to noise hence they have the potential to be more robust classifiers.&#xD;
&#xD;
## Supervised learning&#xD;
&#xD;
Supervised learning applies to algorithms in which a &amp;#039;teacher&amp;#039; continually assesses, or supervises, the classifier&amp;#039;s  performance during training by marking predictions as correct or incorrect. Naturally, this assumes that each case has a valid class label. Learning in this sense relates to the way in which a set of parameter values are adjusted to improve the classifiers&amp;#039; performance.&#xD;
&#xD;
## Unsupervised learning&#xD;
&#xD;
On the other hand, in unsupervised learning there is no teacher and the classifier is left to find its own classes  - known as clusters. The biggest benefits  from an unsupervised classification are likely in knowledge-poor environments, particularly when there are large amounts of unlabeled data. As such clustering are viewed as a means of generating, rather than testing, hypotheses and related classifications.&#xD;
&#xD;
# Classification&#xD;
&#xD;
Classification is the placing of objects into predefined groups.  This type of process is also called &amp;#039;pattern recognition&amp;#039;. Why? The set of samples for which the property of interest and measurements is known is called the training set. The set of measurements that describe each sample in the data set is called a pattern. The determination of the property of interest by assigning a sample to its respective category is called recognition, hence the term pattern recognition. . As such, it is a collection of methods for &amp;#039;supervised  learning&amp;#039;.&#xD;
&#xD;
Clustering is related to classification. Both techniques place objects into groups or classes. The important difference is that the classes are not&#xD;
predefined in a cluster analysis. Instead objects are placed into &amp;#039;natural&amp;#039; groups.Therefore, clustering algorithms are unsupervised.&#xD;
&#xD;
When we deal with large sets of multidimensional data, we can apply standard methods such as PCA (principal component analysis) or clustering.  Both techniques attempt to analyse data without directly using information about the class assignment of the samples.  Although both are powerful methods for uncovering relationships in large multivariate data sets, they are not sufficient for developing a classification rule that can accurately predict the class-membership of an unknown sample.&#xD;
&#xD;
Pattern recognition techniques fall into one of two categories: &#xD;
&#xD;
- Nonparametric discriminants&#xD;
&#xD;
- Similarity-based classifiers&#xD;
&#xD;
Nonparametric discriminants,.such as neural networks, attempt to divide a data space into different regions. In the simplest case, that of a binary&#xD;
classifier, the data space is divided into two regions. Samples that share a common property (e.g. risk type) will be found on one side of the decision surface, whereas those samples comprising the other category will be found on the other side. Classification based on random or chance separation.can be a serious problem if the data set is not sample rich. Because economic datasets usually contain more variables than samples, similarity-based classifiers are generally preferred.&#xD;
&#xD;
A basic assumption in similarity-base classification is that distances between points in the measurement space will be inversely related to their degree of similarity. Using a similarity-based classifier we can determine the class-membership of a sample by examining the class label of the data point closest to it in the measurement space.&#xD;
&#xD;
Classification in *Mathematica* 10 can be efficiently performed with the [Classify][2] command which offers good degree of flexibility and classification method selection.&#xD;
&#xD;
# Classification techniques in Finance&#xD;
&#xD;
Classification can be effectively used in the risk management and large dataset processing where group  information is of particular interest. &#xD;
&#xD;
Consider the following case:  financial institution has large portfolio of loans to its clients.  It wants to establish the method for assessing the quality of lending portfolio by linking the maturity and credit spread on each loan to internal rating categories. We apply the Classification method to analyse the portfolio and to assign each loan to the rating class. Finally we produce the classified loans status based on the rating group ping.&#xD;
&#xD;
# Training set definition&#xD;
&#xD;
The financial institution can define the training set (the template for sample assignment) in the following way:&#xD;
&#xD;
- 6 Rating categories:		AAA,, AA, A, BBB, BB, B&#xD;
&#xD;
- 3 maturity sets:		3 years / 5 years / 10 years&#xD;
&#xD;
- Credit spreads for each maturity / rating&#xD;
&#xD;
        trainset = {{3, 50} -&amp;gt; &amp;#034;AAA&amp;#034;, {5, 70} -&amp;gt; &amp;#034;AAA&amp;#034;, {10, 85} -&amp;gt; &#xD;
            &amp;#034;AAA&amp;#034;, {3, 85} -&amp;gt; &amp;#034;AA&amp;#034;, {5, 145} -&amp;gt; &amp;#034;AA&amp;#034;, {10, 200} -&amp;gt; &#xD;
            &amp;#034;AA&amp;#034;, {3, 120} -&amp;gt; &amp;#034;A&amp;#034;, {5, 200} -&amp;gt; &amp;#034;A&amp;#034;, {10, 260} -&amp;gt; &#xD;
            &amp;#034;A&amp;#034;, {3, 210} -&amp;gt; &amp;#034;BBB&amp;#034;, {5, 300} -&amp;gt; &amp;#034;BBB&amp;#034;, {10, 390} -&amp;gt; &#xD;
            &amp;#034;BBB&amp;#034;, {3, 290} -&amp;gt; &amp;#034;BB&amp;#034;, {5, 370} -&amp;gt; &amp;#034;BB&amp;#034;, {10, 440} -&amp;gt; &#xD;
            &amp;#034;BB&amp;#034;, {3, 360} -&amp;gt; &amp;#034;B&amp;#034;, {5, 470} -&amp;gt; &amp;#034;B&amp;#034;, {10, 550} -&amp;gt; &amp;#034;B&amp;#034;};&#xD;
&#xD;
By isolating credit spreads, we can visualise the training set credit spreads levels below:&#xD;
&#xD;
    sprd = {{50, 70, 85}, {85, 145, 200}, {120, 200, 260}, {210, 300, 390}, {290, 370, 440}, {360, 470, 550}};&#xD;
    BarChart[sprd, ChartLegends -&amp;gt; {3 Y, 5 Y, 10 Y}, &#xD;
     PlotLabel -&amp;gt; Style[&amp;#034;Credit spreads per maturity/rating class&amp;#034;, 15], &#xD;
     ChartLabels -&amp;gt; {{&amp;#034;AAA&amp;#034;, &amp;#034;AA&amp;#034;, &amp;#034;A&amp;#034;, &amp;#034;BBB&amp;#034;, &amp;#034;BB&amp;#034;, &amp;#034;B&amp;#034;}, None}]&#xD;
&#xD;
![enter image description here][3]&#xD;
&#xD;
## Setting the classifier&#xD;
&#xD;
We use the training set defined above to set up the classifier based on similarity measure using k-nearest neighbor method&#xD;
&#xD;
    clsf = Classify[trainset, Method -&amp;gt; &amp;#034;NearestNeighbors&amp;#034;]&#xD;
&#xD;
![enter image description here][4]&#xD;
&#xD;
and obtain the information on the classifier&#xD;
&#xD;
    ClassifierInformation[clsf]&#xD;
&#xD;
![enter image description here][5]&#xD;
&#xD;
We can investigate the classifier further by obtaining additional Information:&#xD;
&#xD;
    ClassifierInformation[clsf, &amp;#034;MethodDescription&amp;#034;]&#xD;
&#xD;
![enter image description here][6]&#xD;
&#xD;
# Classifier testing&#xD;
&#xD;
We can test and validate the classifier with the &amp;lt;ClassifierMeasurements&amp;gt; command. &#xD;
For example, we can define the validation test set as follows:&#xD;
&#xD;
    vset = {{3, 46} -&amp;gt; &amp;#034;AAA&amp;#034;, {5, 81} -&amp;gt; &amp;#034;AAA&amp;#034;, {10, 92} -&amp;gt; &amp;#034;AAA&amp;#034;, {3, 91} -&amp;gt; &#xD;
        &amp;#034;AA&amp;#034;, {5, 155} -&amp;gt; &amp;#034;AA&amp;#034;, {10, 202} -&amp;gt; &amp;#034;AA&amp;#034;, {3, 126} -&amp;gt; &amp;#034;A&amp;#034;, {5, 215} -&amp;gt; &#xD;
        &amp;#034;A&amp;#034;, {10, 259} -&amp;gt; &amp;#034;A&amp;#034;, {3, 219} -&amp;gt; &amp;#034;BBB&amp;#034;, {5, 311} -&amp;gt; &amp;#034;BBB&amp;#034;, {10, 399} -&amp;gt; &#xD;
        &amp;#034;BBB&amp;#034;, {3, 292} -&amp;gt; &amp;#034;BB&amp;#034;, {5, 378} -&amp;gt; &amp;#034;BB&amp;#034;, {10, 442} -&amp;gt; &amp;#034;BB&amp;#034;, {3, 350} -&amp;gt; &#xD;
        &amp;#034;B&amp;#034;, {5, 460} -&amp;gt; &amp;#034;B&amp;#034;, {10, 568} -&amp;gt; &amp;#034;B&amp;#034;};&#xD;
&#xD;
### Testing accuracy of the classifier&#xD;
&#xD;
    cm = ClassifierMeasurements[clsf, vset]&#xD;
    cm[&amp;#034;Accuracy&amp;#034;]&#xD;
&#xD;
![enter image description here][7]&#xD;
&#xD;
`1.`&#xD;
&#xD;
The classifier returns the correct class group ping for all categories with high precision.&#xD;
&#xD;
### Measuring F-Score&#xD;
&#xD;
    cm[&amp;#034;FScore&amp;#034;]&#xD;
&#xD;
`&amp;lt;|&amp;#034;A&amp;#034; -&amp;gt; 1., &amp;#034;AA&amp;#034; -&amp;gt; 1., &amp;#034;AAA&amp;#034; -&amp;gt; 1., &amp;#034;B&amp;#034; -&amp;gt; 1., &amp;#034;BB&amp;#034; -&amp;gt; 1., &amp;#034;BBB&amp;#034; -&amp;gt; 1.|&amp;gt;`&#xD;
&#xD;
### Generating Confusion matrix &#xD;
&#xD;
    cm[&amp;#034;ConfusionMatrixPlot&amp;#034;]&#xD;
&#xD;
![enter image description here][8]&#xD;
&#xD;
The matrix confirms that the classifier assigns the sample test data to the rating classes correctly. There are no overlaps in the assignment.&#xD;
&#xD;
# Applying classifier to the financial data&#xD;
&#xD;
Applying classifier to the financial data&#xD;
&#xD;
Having defined and tested the classifier, we can start applying it to the financial data. Let&amp;#039;s assume that financial institution has 50,000 loans with remaining maturity / market spread information. The sample of the loan portfolio is shown below:&#xD;
&#xD;
    dat2 = Table[{RandomReal[10], RandomInteger[{70, 620}]}, {50000}];&#xD;
    Take[dat2, 75]&#xD;
    ListPlot[%, PlotStyle -&amp;gt; Magenta, PlotLabel -&amp;gt; Style[&amp;#034;Sample loan spreads per maturity&amp;#034;, Blue, 15]]&#xD;
&#xD;
{{8.518356726448882`,454},{9.144298651160256`,608},{2.855364088031351`,184},{6.0566791640110615`,282},{1.5475654397289134`,266},{2.6417875173168994`,315},{4.966702524403626`,231},{0.19793692995662404`,605},{4.478200060877295`,213},{9.292431559943076`,294},{9.28184530814859`,447},{4.204004132022266`,234},{2.4319873689548466`,296},{0.34979911441219613`,499},{4.188999084728859`,139},{9.94074933345011`,392},{3.4739994419209292`,429},{8.95426428111189`,206},{8.554799166603996`,367},{1.4762114253028358`,498},{3.1821905760430784`,520},{9.366754802446565`,473},{1.6701704343156525`,244},{1.376279011603522`,232},{9.566319795447356`,333},{0.8703633914472597`,564},{6.71837887079888`,452},{7.302098986957059`,441},{2.6238815271294573`,239},{1.5336733840535572`,157},{1.4641136928541592`,146},{0.6465197801125662`,198},{1.222074695630404`,315},{5.702826552095841`,339},{6.731378893601473`,552},{8.808804286652013`,195},{0.6739420557112723`,314},{6.378960901113356`,393},{5.72547626395229`,445},{9.460117372811034`,417},{7.24575011914737`,376},{3.542651788089211`,280},{9.266105852374011`,473},{0.07409813721899816`,238},{6.042215952909746`,412},{4.264033025081259`,176},{2.6031280721072108`,541},{0.30796996377340946`,240},{7.365932988439827`,339},{6.898537558573874`,269},{7.588189071934799`,80},{7.64691230466779`,173},{4.097033804059016`,456},{7.365705637020458`,141},{6.499421726202534`,578},{8.431948572861224`,351},{6.241593889798619`,540},{5.458576916155449`,551},{1.2166050064107576`,340},{5.5963915988722395`,146},{5.958260855340793`,235},{1.5241468668957854`,595},{9.71283120935691`,382},{3.604748368454281`,226},{6.595824594015976`,431},{5.125769853255001`,619},{1.9166780841799138`,121},{9.506908583817971`,526},{2.793767635980249`,574},{5.83433511143844`,186},{7.708892750256794`,484},{4.099308138686737`,568},{5.6066580959611265`,527},{4.377895268594408`,146},{6.840495656634236`,380}}&#xD;
&#xD;
![enter image description here][9]&#xD;
&#xD;
We apply the classifier to the spread data:&#xD;
&#xD;
    clsloans = clsf[#] &amp;amp; /@ dat2;&#xD;
&#xD;
and group the results into rating classes&#xD;
&#xD;
    rtdgroup = {&amp;#034;AAA&amp;#034;, &amp;#034;AA&amp;#034;, &amp;#034;A&amp;#034;, &amp;#034;BBB&amp;#034;, &amp;#034;BB&amp;#034;, &amp;#034;B&amp;#034;};&#xD;
    rtdfreq = Table[Count[clsloans, i], {i, rtdgroup}]&#xD;
    BarChart[rtdfreq, ChartStyle -&amp;gt; &amp;#034;Rainbow&amp;#034;, ChartLegends -&amp;gt; rtdgroup, &#xD;
     ChartLabels -&amp;gt; rtdgroup, LabelingFunction -&amp;gt; Above, &#xD;
     PlotLabel -&amp;gt; Style[&amp;#034;Rating classification of 50,000 loans portfolio&amp;#034;, Blue, 15]]&#xD;
&#xD;
`{720, 9003, 6481, 8878, 6867, 18051}`&#xD;
&#xD;
![enter image description here][10]&#xD;
&#xD;
We can see that the largest proportion of loans falls into B-rated category and the smallest to the AAA category. This is naturally expected.&#xD;
Further aggregation of the classified results can be done on Investment grade (&amp;gt;BB) and Non-Investment grade scale:&#xD;
&#xD;
    {Total[rtdfreq] - Total[Take[rtdfreq, -2]], Total[Take[rtdfreq, -2]]};&#xD;
    BarChart[%, ChartStyle -&amp;gt; &amp;#034;Pastel&amp;#034;, ChartLegends -&amp;gt; {&amp;#034;IG Loans&amp;#034;, &amp;#034;Non-IG Loans&amp;#034;}, &#xD;
     LabelingFunction -&amp;gt; Above, PlotLabel -&amp;gt; Style[&amp;#034;Investment grade / Non-investment grade split&amp;#034;, Blue, 15]]&#xD;
&#xD;
![enter image description here][11]&#xD;
&#xD;
We can see equal split between IG  and non-IG loans.&#xD;
&#xD;
## Dynamic update of the portfolio&#xD;
&#xD;
The set-up classifier can work with dynamically changing portfolio. For example, we can add 100 new loans to the existing portfolio and visualise the result:&#xD;
&#xD;
    newport=Table[Count[Join[clsloans,clsf[#]&amp;amp;/@&#xD;
    	Table[{RandomReal[10],RandomInteger[{70,620}]},{50}]],i],{i,rtdgroup}];&#xD;
    {BarChart[rtdfreq,ChartStyle-&amp;gt;&amp;#034;Rainbow&amp;#034;,ChartLegends-&amp;gt;rtdgroup,ChartLabels-&amp;gt;rtdgroup,&#xD;
    	LabelingFunction-&amp;gt;Above,PlotLabel-&amp;gt;Style[&amp;#034;Existing portfolio&amp;#034;,Blue,15],ImageSize-&amp;gt;290],&#xD;
    BarChart[newport,ChartStyle-&amp;gt;&amp;#034;TemperatureMap&amp;#034;,ChartLegends-&amp;gt;rtdgroup,ChartLabels-&amp;gt;rtdgroup,&#xD;
    	LabelingFunction-&amp;gt;Above,PlotLabel-&amp;gt;Style[&amp;#034;Portfolio with added 100 new assets&amp;#034;,Blue,15],ImageSize-&amp;gt;290]}&#xD;
&#xD;
![enter image description here][12]&#xD;
&#xD;
We can also simulate the generation of new load assets and see how they are dynamically classified using the classification defined on the training set.&#xD;
&#xD;
    Manipulate[BarChart[Table[Count[clsf[#] &amp;amp; /@ &#xD;
         Table[{RandomReal[10], RandomInteger[{70, 620}]}, {\[Alpha]}], i], &#xD;
        {i, rtdgroup}], ChartStyle -&amp;gt; &amp;#034;DarkRainbow&amp;#034;, ChartLegends -&amp;gt; rtdgroup, &#xD;
      ChartLabels -&amp;gt; rtdgroup, LabelingFunction -&amp;gt; Above, &#xD;
      PlotLabel -&amp;gt; Style[&amp;#034;Classified new loans in the portfolio&amp;#034;, Blue, 15]], &#xD;
        {{\[Alpha], 10, &amp;#034;Nb of new loans&amp;#034;}, 0, 100, 1}]&#xD;
&#xD;
# Review of the classification algorithms&#xD;
&#xD;
We can further investigate the behaviour of the classification algorithm by looking at the probability assignment boundaries for each class. We select the 5 year horizon for presentation purposes and pick the IG group:&#xD;
&#xD;
    {Plot[clsf[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;AAA&amp;#034;}],{x,0,150},PlotStyle-&amp;gt;Blue,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;AAA Rated&amp;#034;,13]],&#xD;
    Plot[clsf[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;AA&amp;#034;}],{x,0,240},PlotStyle-&amp;gt;Magenta,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;AA Rated&amp;#034;,13]],&#xD;
    Plot[clsf[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;A&amp;#034;}],{x,0,300},PlotStyle-&amp;gt;Green,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;A Rated&amp;#034;,13]],&#xD;
    Plot[clsf[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;BBB&amp;#034;}],{x,0,400},PlotStyle-&amp;gt;Orange,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;BBB Rated&amp;#034;,13]]}&#xD;
&#xD;
![enter image description here][13]&#xD;
&#xD;
This &amp;#039;digital-alike&amp;#039; behaviour of the NearestNeighbors algorithm is the one we actually desire in the probabilistic setting. This ensures limited overlap / spillage between the class boundaries.&#xD;
&#xD;
When we selected  other classification algorithms, the result can be quite different. This is demonstrated below:&#xD;
&#xD;
## Random Forest classification&#xD;
&#xD;
    clsfRF = Classify[trainset, Method -&amp;gt; &amp;#034;RandomForest&amp;#034;];&#xD;
&#xD;
    method=clsfRF;&#xD;
    {Plot[method[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;AAA&amp;#034;}],{x,0,150},PlotStyle-&amp;gt;Blue,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;AAA Rated&amp;#034;,13]],&#xD;
    Plot[method[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;AA&amp;#034;}],{x,0,240},PlotStyle-&amp;gt;Magenta,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;AA Rated&amp;#034;,13]],&#xD;
    Plot[method[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;A&amp;#034;}],{x,0,300},PlotStyle-&amp;gt;Green,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;A Rated&amp;#034;,13]],&#xD;
    Plot[method[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;BBB&amp;#034;}],{x,0,400},PlotStyle-&amp;gt;Orange,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;BBB Rated&amp;#034;,13]]}&#xD;
&#xD;
![enter image description here][14]&#xD;
&#xD;
## Neural Networks classification&#xD;
&#xD;
    clsfNN = Classify[trainset, Method -&amp;gt; &amp;#034;NeuralNetwork&amp;#034;];&#xD;
&#xD;
    method=clsfNN;&#xD;
    {Plot[method[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;AAA&amp;#034;}],{x,0,150},PlotStyle-&amp;gt;Blue,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;AAA Rated&amp;#034;,13]],&#xD;
    Plot[method[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;AA&amp;#034;}],{x,0,240},PlotStyle-&amp;gt;Magenta,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;AA Rated&amp;#034;,13]],&#xD;
    Plot[method[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;A&amp;#034;}],{x,0,300},PlotStyle-&amp;gt;Green,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;A Rated&amp;#034;,13]],&#xD;
    Plot[method[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;BBB&amp;#034;}],{x,0,400},PlotStyle-&amp;gt;Orange,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;BBB Rated&amp;#034;,13]]}&#xD;
&#xD;
![enter image description here][15]&#xD;
&#xD;
## Support Vector Machine&#xD;
&#xD;
    clsfSVM = Classify[trainset, Method -&amp;gt; &amp;#034;SupportVectorMachine&amp;#034;];&#xD;
&#xD;
    method=clsfSVM;&#xD;
    {Plot[method[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;AAA&amp;#034;}],{x,0,150},PlotStyle-&amp;gt;Blue,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;AAA Rated&amp;#034;,13]],&#xD;
    Plot[method[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;AA&amp;#034;}],{x,0,240},PlotStyle-&amp;gt;Magenta,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;AA Rated&amp;#034;,13]],&#xD;
    Plot[method[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;A&amp;#034;}],{x,0,300},PlotStyle-&amp;gt;Green,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;A Rated&amp;#034;,13]],&#xD;
    Plot[method[{5,x},{&amp;#034;Probability&amp;#034;,&amp;#034;BBB&amp;#034;}],{x,0,400},PlotStyle-&amp;gt;Orange,Filling-&amp;gt;Axis,PlotLabel-&amp;gt;Style[&amp;#034;BBB Rated&amp;#034;,13]]}&#xD;
&#xD;
We observe very different classification schemes when the algorithm changes from NearestNeighbors to other alternatives. Whilst RandomForest generates patchy classification pattern, artificial NeuralNetworks or SupportVectorMachine produce smooth probabilistic curves. However, such smoothness may be less desirable in the rating assignment context. This is demonstrated below:&#xD;
&#xD;
### Example:   we want to test  4.5 years maturity and  110 bp spread.&#xD;
&#xD;
NearestNeighbors sees this as A-rated asset given the proximity measure&#xD;
&#xD;
    clsf[{4.5, 110}, &amp;#034;Probabilities&amp;#034;]&#xD;
&#xD;
`&amp;lt;|&amp;#034;A&amp;#034; -&amp;gt; 0.722222, &amp;#034;AA&amp;#034; -&amp;gt; 0.0555556, &amp;#034;AAA&amp;#034; -&amp;gt; 0.0555556, &amp;#034;B&amp;#034; -&amp;gt; 0.0555556, &amp;#034;BB&amp;#034; -&amp;gt; 0.0555556, &amp;#034;BBB&amp;#034; -&amp;gt; 0.0555556|&amp;gt;`&#xD;
&#xD;
RandomForest generates multiple set of statistically important probabilities with less clear-cut assignment&#xD;
&#xD;
    clsfRF[{4.5, 110}, &amp;#034;Probabilities&amp;#034;]&#xD;
&#xD;
`&amp;lt;|&amp;#034;A&amp;#034; -&amp;gt; 0.254235, &amp;#034;AA&amp;#034; -&amp;gt; 0.212853, &amp;#034;AAA&amp;#034; -&amp;gt; 0.167341, &amp;#034;B&amp;#034; -&amp;gt; 0.119395, &amp;#034;BB&amp;#034; -&amp;gt; 0.110873, &amp;#034;BBB&amp;#034; -&amp;gt; 0.135303|&amp;gt;`&#xD;
&#xD;
NeuralNetworks sees this spread as primarily BBB-rates asset, but there is still strong support for A-rating as well&#xD;
&#xD;
    clsfNN[{4.5, 110}, &amp;#034;Probabilities&amp;#034;]&#xD;
&#xD;
`&amp;lt;|&amp;#034;A&amp;#034; -&amp;gt; 0.316899, &amp;#034;AA&amp;#034; -&amp;gt; 0.0229639, &amp;#034;AAA&amp;#034; -&amp;gt; 0.00319862, &amp;#034;B&amp;#034; -&amp;gt; 0.00256616, &amp;#034;BB&amp;#034; -&amp;gt; 0.0709275, &amp;#034;BBB&amp;#034; -&amp;gt; 0.583445|&amp;gt;`&#xD;
&#xD;
SupportVectorMachine provides similarly a set of statistically significant probabilities - seeing this as A-rates asset with other still being significant for quick conclusion&#xD;
&#xD;
    clsfSVM[{4.5, 110}, &amp;#034;Probabilities&amp;#034;]&#xD;
&#xD;
`&amp;lt;|&amp;#034;A&amp;#034; -&amp;gt; 0.415746, &amp;#034;AA&amp;#034; -&amp;gt; 0.210153, &amp;#034;AAA&amp;#034; -&amp;gt; 0.105478, &amp;#034;B&amp;#034; -&amp;gt; 0.0119384, &amp;#034;BB&amp;#034; -&amp;gt; 0.0444652, &amp;#034;BBB&amp;#034; -&amp;gt; 0.212219|&amp;gt;`&#xD;
&#xD;
The **NearestNeighbors** classification scheme produces the most consistent result in terms of data association with the rating class. In the context of this particular assignment this is the preferred method.&#xD;
&#xD;
# Conclusion&#xD;
&#xD;
Classification is a powerful method for data organisation and dimensionality reduction in supervised machine learning. It is particularly useful when data has to be organised into class structure or given certain association with structural hierarchy. This is ideal for finding patterns in large datasets.&#xD;
&#xD;
Classification is well-suited technique for financial data analysis. This was demonstrated on the credit rating case where simple implementation led to a power full and robust scheme that was able to classify large portfolios with real-time updates. As such, classification is therefore essential for prudent risk management.&#xD;
&#xD;
&#xD;
  [1]: /c/portal/getImageAttachment?filename=Classifcnimage.jpg&amp;amp;userId=387433&#xD;
  [2]: http://reference.wolfram.com/language/ref/Classify.html&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=sadfe34q5tyrhsgfdsa.png&amp;amp;userId=11733&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=dg34qgre.png&amp;amp;userId=11733&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=dfg5q4ywhntfgbsear4t54hr.png&amp;amp;userId=11733&#xD;
  [6]: http://community.wolfram.com//c/portal/getImageAttachment?filename=34erwth.png&amp;amp;userId=11733&#xD;
  [7]: http://community.wolfram.com//c/portal/getImageAttachment?filename=asdfq35yfdhgs.png&amp;amp;userId=11733&#xD;
  [8]: http://community.wolfram.com//c/portal/getImageAttachment?filename=sdfacbxnmjguityer54.png&amp;amp;userId=11733&#xD;
  [9]: http://community.wolfram.com//c/portal/getImageAttachment?filename=wer345tehrwrg5q3t.png&amp;amp;userId=11733&#xD;
  [10]: http://community.wolfram.com//c/portal/getImageAttachment?filename=gfjhglkghjfg4356yrteaw.png&amp;amp;userId=11733&#xD;
  [11]: http://community.wolfram.com//c/portal/getImageAttachment?filename=g5qy46whrt5q34hte.png&amp;amp;userId=11733&#xD;
  [12]: http://community.wolfram.com//c/portal/getImageAttachment?filename=edffnbfg54hqt.png&amp;amp;userId=11733&#xD;
  [13]: http://community.wolfram.com//c/portal/getImageAttachment?filename=sadft5rnhfgbd.png&amp;amp;userId=11733&#xD;
  [14]: http://community.wolfram.com//c/portal/getImageAttachment?filename=fgt57697oiujtyhr.png&amp;amp;userId=11733&#xD;
  [15]: http://community.wolfram.com//c/portal/getImageAttachment?filename=gdft45645y54yhrtghfsd.png&amp;amp;userId=11733</description>
    <dc:creator>Igor Hlivka</dc:creator>
    <dc:date>2015-03-24T16:20:34Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1732399">
    <title>[WSC19] Automated spot the difference</title>
    <link>https://community.wolfram.com/groups/-/m/t/1732399</link>
    <description>Description&#xD;
-----------&#xD;
&#xD;
I created a [website][1] that automatically makes a spot-the-difference challenge from various images. When given an image, I first find the specific items within the picture using ImageContents. I then remove or edit each of those contents and put the edited subimage back onto the original image, or in the case of removal, use InPaint to cover the gap.&#xD;
&#xD;
When the user arrives at the site, they choose a difficulty level, whether they would like one image or all of the images in that difficulty range, and an image. They can click to the very right in order to reveal the correct solution.&#xD;
&#xD;
General Image Functions&#xD;
-----------------------&#xD;
&#xD;
The heart of the functionality in my project is ImageContents, a function which uses machine learning to find and identify things in a given image. Though ImageContents uses the same idea as ImageIdentify, it can find items in subimages and not only the entire image. For example, lets take the ImageContents of this elephant image. It finds each elephant separately.&#xD;
&#xD;
![enter image description here][2]&#xD;
&#xD;
One of the first problems I ran into was that Inpaint will sometimes use parts of the original image which contain other objects: for example, Inpaint might successfully cover the large elephant, but catch the small elephant in its mask, covering the large elephant with an unsettling floating baby elephant head.&#xD;
![enter image description here][3]&#xD;
&#xD;
In order to solve this, I created my first function: `mask` which solves the issue of not being able to auto-generate masks based solely on their bounding boxes. &#xD;
&#xD;
    boundingboxes[image_]:=Quiet[Check[&#xD;
      List @@@ Flatten@&#xD;
        Values@Normal@ImageContents[image, All, &amp;#034;BoundingBox&amp;#034;], {}]]&#xD;
The next function I created is called `expunge`, which utilizes `mask` to Inpaint the image contents.&#xD;
&#xD;
    mask[{{col1_, row1_}, {col2_, row2_}}, {nrows_, ncols_}, &#xD;
      previous_: None] := &#xD;
     Table[If[nrows - row2 &amp;lt; row &amp;lt;= nrows - row1 + 1 &amp;amp;&amp;amp; &#xD;
        col1 &amp;lt; col &amp;lt;= col2, 1, &#xD;
       If[previous === None, 0, previous[[row, col]]]], {row, &#xD;
       nrows}, {col, ncols}]&#xD;
The next function I made is called ImageMapAt. ImageTrim trims the contents out of the image and applies the given function to the trimmed contents. ImageMapAt uses ImageCompose to shove the edited contents back into the original image, one at a time. Also, ImageMapAt uses the parameters {Left,Top} to align the edited contents correctly when pasting them back into the image, so it doesn&amp;#039;t return outputs like this:&#xD;
&#xD;
![enter image description here][4]&#xD;
&#xD;
## Image Difference Functions ##&#xD;
Once all my general functions were working, my next step was to create functions to be applied to the images to automate the differences. These functions were based on built-in functions in the Wolfram Language, but specified to visible yet not too obvious variations. These include `blurred`, which blurs an image by 2 units, `darker` which darkens dominant colors, `aquarecolor` which replaces a dominant color with part of the gradient Aquamarine, and various others.&#xD;
## Displaying Image Differences ##&#xD;
Once I had created differences, my next step was to display them. The idea is simple, merely subtract the original image from the one with differences. The difficult part was finding a way to display them nicely as the default had the differences placed on a black background making them hard to see and the ColorNegated version of it was too bright, so I used ImageAdjust. Here are some of the results.&#xD;
&#xD;
![enter image description here][5]&#xD;
## Image Distance Sorting ##&#xD;
Now that I had created and displayed the differences, I sorted the images into the order of larger changes to smaller ones using ImageDistance, because the larger the distance is, the bigger the change. For example, compare these two distances. Wouldnt you agree the first one is roughly ten times easier than the second?&#xD;
![enter image description here][6]&#xD;
![enter image description here][7]&#xD;
## Website Code ##&#xD;
I then created LibraryAdd, a function that is used to add images into my curated image library. Lastly, I created my website. The basic idea is that next to the original (left) and the new image (right), there will be a blank/white image that I refer to as &amp;#034;blank.&amp;#034; The user clicks on the &amp;#034;empty space&amp;#034; once they think they know the difference, and then the correct difference is shown. If it is clicked again, the image returns to its original blank state. The code is shown below.&#xD;
&#xD;
    CloudDeploy[&#xD;
     FormFunction[{&amp;#034;difficulty&amp;#034; -&amp;gt; {&amp;#034;easy&amp;#034; -&amp;gt; {0, 1/4}, &#xD;
         &amp;#034;medium&amp;#034; -&amp;gt; {1/4, 1/2}, &amp;#034;hard&amp;#034; -&amp;gt; {1/2, 3/4}, &#xD;
         &amp;#034;impossible&amp;#034; -&amp;gt; {3/4, 1}}, &amp;#034;selection&amp;#034; -&amp;gt; {&amp;#034;random&amp;#034;, &amp;#034;all&amp;#034;},&#xD;
       &amp;#034;image&amp;#034; -&amp;gt; (CloudImport[First@# &amp;lt;&amp;gt; &amp;#034;/1.png&amp;#034;] -&amp;gt; First[#] &amp;amp; /@ &#xD;
          Select[CloudObjects[&#xD;
            &amp;#034;gallery&amp;#034;], ! StringContainsQ[First@#, &amp;#034;.png&amp;#034;] &amp;amp;])},&#xD;
      &#xD;
      With[{total = Length[CloudObjects[#image &amp;lt;&amp;gt; &amp;#034;/&amp;#034;]]/2,&#xD;
         &#xD;
         original = #image &amp;lt;&amp;gt; &amp;#034;/1&amp;#034;},&#xD;
        &#xD;
        Grid[With[{orderly = &#xD;
            Table[With[{new = #image &amp;lt;&amp;gt; &amp;#034;/&amp;#034; &amp;lt;&amp;gt; ToString[i]},&#xD;
              &#xD;
              &amp;#034;&amp;lt;img height=\&amp;#034;200px\&amp;#034; src=\&amp;#034;&amp;#034; &amp;lt;&amp;gt; If[#2, blank, #] &amp;lt;&amp;gt; &amp;#034;\&amp;#034;&amp;#034; &amp;lt;&amp;gt;&#xD;
                  If[#2, &#xD;
                  &amp;#034; onclick=\&amp;#034;javascript:this.src=(this.src==&amp;#039;&amp;#034; &amp;lt;&amp;gt; # &amp;lt;&amp;gt; &#xD;
                   &amp;#034;&amp;#039; ? &amp;#039;&amp;#034; &amp;lt;&amp;gt; blank &amp;lt;&amp;gt; &amp;#034;&amp;#039; : &amp;#039;&amp;#034; &amp;lt;&amp;gt; # &amp;lt;&amp;gt; &amp;#034;&amp;#039;);\&amp;#034;&amp;#034;, &amp;#034;&amp;#034;] &amp;lt;&amp;gt; &#xD;
                 &amp;#034;&amp;gt;&amp;#034; &amp;amp; @@@ {original &amp;lt;&amp;gt; &amp;#034;.png&amp;#034; -&amp;gt; False, &#xD;
                new &amp;lt;&amp;gt; &amp;#034;.png&amp;#034; -&amp;gt; False, new &amp;lt;&amp;gt; &amp;#034;a.png&amp;#034; -&amp;gt; True}],&#xD;
             {i, TakeQuantile[Range[2, total], #difficulty]}]}, &#xD;
          If[#[&amp;#034;selection&amp;#034;] === &amp;#034;random&amp;#034;, {RandomChoice[orderly]}, &#xD;
           orderly]]]] &amp;amp;, &#xD;
      AppearanceRules -&amp;gt; &amp;lt;|&amp;#034;Title&amp;#034; -&amp;gt; &amp;#034;Spot the Difference&amp;#034;, &#xD;
        &amp;#034;Description&amp;#034; -&amp;gt; &#xD;
         &amp;#034;Choose a difficulty, whether you would like to see the \&#xD;
    solutions or not, and an image, then hit submit to try to spot the \&#xD;
    difference between the original image on the left and the edited one \&#xD;
    on the right. &amp;lt;i&amp;gt;&amp;lt;a \&#xD;
    href=\&amp;#034;mailto:stella@maymin.com\&amp;#034;&amp;gt;stella@maymin.com&amp;lt;/a&amp;gt;&amp;lt;/i&amp;gt;&amp;#034;|&amp;gt;], \&#xD;
    &amp;#034;spot.me&amp;#034;, Permissions -&amp;gt; &amp;#034;Public&amp;#034;]&#xD;
## Future Work ##&#xD;
In the future, as an extension of my website, I would like to find a way to create more of a game, perhaps by using dynamics. Another extension may be to create a timer counting in seconds how long it took the user to click the correct difference, or a counter of how many incorrect clicks on the Locator there were. Using those high scores, I think it might be possible to create a Leaderboard across all users. This would create a competition between users all over the world, so they can try to beat each others high scores in the race to the top. Lastly, a simpler extension is to create the option of allowing the user to upload their own images, which would be saved in my master library. This would let users play with images others have uploaded. &#xD;
&#xD;
&#xD;
## Acknowledgements ##&#xD;
I would like to thank my mentor, Rory Fougler, for helping me with my code every step of the way. It really made a huge difference. I would also like to thank Chip Hurst for providing various insights and helpful functions throughout my project. Lastly, I would like to thank Mads Bahrami, Kyle Keane, and Anna Musser for making this entire experience truly unforgettable. Overall, I am so grateful for my knowledge and capabilities now, thanks to my stay here at the Wolfram High School Summer Camp.&#xD;
&#xD;
&#xD;
  [1]: https://www.wolframcloud.com/obj/stella/spot.me&#xD;
  [2]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ImageContentselephants.png&amp;amp;userId=1720407&#xD;
  [3]: https://community.wolfram.com//c/portal/getImageAttachment?filename=OopsPost.png&amp;amp;userId=1720407&#xD;
  [4]: https://community.wolfram.com//c/portal/getImageAttachment?filename=oopsididitagainpost.png&amp;amp;userId=1720407&#xD;
  [5]: https://community.wolfram.com//c/portal/getImageAttachment?filename=orderlydiffs.png&amp;amp;userId=1720407&#xD;
  [6]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ImageDistance01.PNG&amp;amp;userId=1720407&#xD;
  [7]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ImageDistance03.PNG&amp;amp;userId=1720407</description>
    <dc:creator>Stella Maymin</dc:creator>
    <dc:date>2019-07-12T01:28:57Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1016315">
    <title>Higgs Boson Classification via Neural Network</title>
    <link>https://community.wolfram.com/groups/-/m/t/1016315</link>
    <description>![enter image description here][1]&#xD;
&#xD;
# Introduction &#xD;
&#xD;
So here is a simple approach that applies Wolfram Language machine learning functions to a classification problem for finding possible Higgs particles. It uses a labeled data set with 30 numerical physical attributes (things like measured spins, angles, energies, etc.) and with labels being either &amp;#039;signal&amp;#039; (s) or &amp;#039;background&amp;#039; (b). The attached notebook runs through a sample analysis in the Wolfram Language: importing the training data, cleaning it up for using it, setting up a neural network, training the network with the data, and finally checking how well the trained neural network does at making predictions. Here is the description of data from the source website at KAGGLE:&#xD;
&#xD;
&amp;gt; Discovery of the long awaited Higgs boson was announced July 4, 2012 and confirmed six months later. 2013 saw a number of prestigious awards, including a Nobel prize. But for physicists, the discovery of a new particle means the beginning of a long and difficult quest to measure its characteristics and determine if it fits the current model of nature.&#xD;
&#xD;
&amp;gt; A key property of any particle is how often it decays into other particles. ATLAS is a particle physics experiment taking place at the Large Hadron Collider at CERN that searches for new particles and processes using head-on collisions of protons of extraordinarily high energy. The ATLAS experiment has recently observed a signal of the Higgs boson decaying into two tau particles, but this decay is a small signal buried in background noise. &#xD;
&#xD;
&amp;gt; The goal of the Higgs Boson Machine Learning Challenge is to explore the potential of advanced machine learning methods to improve the discovery significance of the experiment. No knowledge of particle physics is required. Using simulated data with features characterizing events detected by ATLAS, your task is to classify events into &amp;#034;tau tau decay of a Higgs boson&amp;#034; versus &amp;#034;background.&amp;#034; &#xD;
&#xD;
&amp;gt; The winning method may eventually be applied to real data and the winners may be invited to CERN to discuss their results with high energy physicists.&#xD;
&#xD;
# References and sources&#xD;
&#xD;
- [Learning to discover: the Higgs boson machine learning challenge][2]&#xD;
- [KAGGLE: Higgs Boson Machine Learning Challenge][3]&#xD;
- [Opendata ATLAS][4]&#xD;
&#xD;
# Training data&#xD;
&#xD;
Import the training data:&#xD;
&#xD;
    training = Import[&amp;#034;D:\\machinelearning\\higgs\\training\\training.csv&amp;#034;, &amp;#034;Data&amp;#034;];&#xD;
    Dimensions[training]&#xD;
&#xD;
`{250001, 33}`&#xD;
&#xD;
Look at the data fields (they are described in the pdf link above). &amp;#034;EventId&amp;#034; should not be used as part of the training, since it has no predictive value. The last column &amp;#034;Label&amp;#034; is the classification (s=signal, b=background)&#xD;
&#xD;
    training[[1]]&#xD;
&#xD;
`{&amp;#034;EventId&amp;#034;, &amp;#034;DER_mass_MMC&amp;#034;, &amp;#034;DER_mass_transverse_met_lep&amp;#034;, \&#xD;
&amp;#034;DER_mass_vis&amp;#034;, &amp;#034;DER_pt_h&amp;#034;, &amp;#034;DER_deltaeta_jet_jet&amp;#034;, \&#xD;
&amp;#034;DER_mass_jet_jet&amp;#034;, &amp;#034;DER_prodeta_jet_jet&amp;#034;, &amp;#034;DER_deltar_tau_lep&amp;#034;, \&#xD;
&amp;#034;DER_pt_tot&amp;#034;, &amp;#034;DER_sum_pt&amp;#034;, &amp;#034;DER_pt_ratio_lep_tau&amp;#034;, \&#xD;
&amp;#034;DER_met_phi_centrality&amp;#034;, &amp;#034;DER_lep_eta_centrality&amp;#034;, &amp;#034;PRI_tau_pt&amp;#034;, \&#xD;
&amp;#034;PRI_tau_eta&amp;#034;, &amp;#034;PRI_tau_phi&amp;#034;, &amp;#034;PRI_lep_pt&amp;#034;, &amp;#034;PRI_lep_eta&amp;#034;, \&#xD;
&amp;#034;PRI_lep_phi&amp;#034;, &amp;#034;PRI_met&amp;#034;, &amp;#034;PRI_met_phi&amp;#034;, &amp;#034;PRI_met_sumet&amp;#034;, \&#xD;
&amp;#034;PRI_jet_num&amp;#034;, &amp;#034;PRI_jet_leading_pt&amp;#034;, &amp;#034;PRI_jet_leading_eta&amp;#034;, \&#xD;
&amp;#034;PRI_jet_leading_phi&amp;#034;, &amp;#034;PRI_jet_subleading_pt&amp;#034;, \&#xD;
&amp;#034;PRI_jet_subleading_eta&amp;#034;, &amp;#034;PRI_jet_subleading_phi&amp;#034;, &amp;#034;PRI_jet_all_pt&amp;#034;, \&#xD;
&amp;#034;Weight&amp;#034;, &amp;#034;Label&amp;#034;}`&#xD;
&#xD;
Sample vector:&#xD;
&#xD;
    training[[2]]&#xD;
&#xD;
`{100000, 138.47, 51.655, 97.827, 27.98, 0.91, 124.711, 2.666, 3.064, \&#xD;
41.928, 197.76, 1.582, 1.396, 0.2, 32.638, 1.017, 0.381, 51.626, \&#xD;
2.273, -2.414, 16.824, -0.277, 258.733, 2, 67.435, 2.15, 0.444, \&#xD;
46.062, 1.24, -2.475, 113.497, 0.00265331, &amp;#034;s&amp;#034;}`&#xD;
&#xD;
Set up a simple neural network (this can be tinkered with to improve the results):&#xD;
&#xD;
    net=NetInitialize[&#xD;
    NetChain[{&#xD;
    LinearLayer[3000],Ramp,LinearLayer[3000],Ramp,LinearLayer[2],SoftmaxLayer[]&#xD;
    },&#xD;
    &amp;#034;Input&amp;#034;-&amp;gt;{30},&#xD;
    &amp;#034;Output&amp;#034;-&amp;gt;NetDecoder[{&amp;#034;Class&amp;#034;,{&amp;#034;b&amp;#034;,&amp;#034;s&amp;#034;}}]&#xD;
    ]]&#xD;
&#xD;
![enter image description here][5]&#xD;
&#xD;
Set up the training data:&#xD;
&#xD;
    data = Map[Take[#, {2, 31}] -&amp;gt; Last[#] &amp;amp;, Drop[training, 1]];&#xD;
&#xD;
Numerical vectors that each point to a classification (s or b):&#xD;
&#xD;
    RandomSample[data, 3]&#xD;
&#xD;
`{{87.06, 23.069, 67.711, 162.488, -999., -999., -999., 0.903, 4.245, &#xD;
   318.43, 0.523, 0.839, -999., 105.019, -0.404, 1.612, &#xD;
   54.943, -0.898, 0.855, 13.541, 1.729, 409.232, 1, &#xD;
   158.469, -1.363, -1.762, -999., -999., -999., 158.469} -&amp;gt; &#xD;
  &amp;#034;b&amp;#034;, {163.658, 55.559, 116.84, 50.019, -999., -999., -999., 2.855, &#xD;
   38.623, 130.132, 0.906, 1.359, -999., 51.993, 0.36, 2.142, &#xD;
   47.112, -0.932, -1.596, 22.782, 2.663, 191.557, 1, 31.026, -2.333, &#xD;
   0.739, -999., -999., -999., 31.026} -&amp;gt; &#xD;
  &amp;#034;b&amp;#034;, {100.248, 27.109, 60.729, 132.094, -999., -999., -999., 1.405, &#xD;
   10.063, 218.474, 0.541, 1.414, -999., 62.519, -0.401, -1.974, &#xD;
   33.817, -0.893, -0.657, 54.857, -1.298, 396.228, 1, &#xD;
   122.137, -2.369, 1.689, -999., -999., -999., 122.137} -&amp;gt; &amp;#034;s&amp;#034;}`&#xD;
&#xD;
# Training &#xD;
&#xD;
    Length[data]&#xD;
&#xD;
`250000`&#xD;
&#xD;
    {tdata,vdata}=TakeDrop[data,240000];&#xD;
    result=NetTrain[net,tdata,TargetDevice-&amp;gt;&amp;#034;GPU&amp;#034;,ValidationSet-&amp;gt;Scaled[0.1],MaxTrainingRounds-&amp;gt;1000]&#xD;
&#xD;
![enter image description here][6]&#xD;
&#xD;
    DumpSave[&amp;#034;D:\\machinelearning\\higgs\\higgs.mx&amp;#034;, result];&#xD;
&#xD;
# Testing &#xD;
&#xD;
This is the test data (unlabeled):&#xD;
&#xD;
    test = Import[&amp;#034;D:\\machinelearning\\higgs\\test\\test.csv&amp;#034;, &amp;#034;Data&amp;#034;];&#xD;
&#xD;
Extract the validation data:&#xD;
&#xD;
    validate = Map[Take[#, {2, 31}] &amp;amp;, Drop[test, 1]];&#xD;
&#xD;
Predictions made on the unlabeled data:&#xD;
&#xD;
    result /@ RandomSample[validate, 5]&#xD;
&#xD;
`{&amp;#034;b&amp;#034;, &amp;#034;b&amp;#034;, &amp;#034;s&amp;#034;, &amp;#034;b&amp;#034;, &amp;#034;b&amp;#034;}`&#xD;
&#xD;
Sample from the labeled data and compute classifier statistics:&#xD;
&#xD;
    cm = ClassifierMeasurements[result, RandomSample[vdata, 1000]]&#xD;
&#xD;
&#xD;
![enter image description here][7]&#xD;
&#xD;
    cm[&amp;#034;Accuracy&amp;#034;]&#xD;
&#xD;
`0.846`&#xD;
&#xD;
Plot the confusion matrix:&#xD;
&#xD;
    cm[&amp;#034;ConfusionMatrixPlot&amp;#034;]&#xD;
&#xD;
![enter image description here][8]&#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ATLASEXP_image.png&amp;amp;userId=20103&#xD;
  [2]: https://higgsml.lal.in2p3.fr/files/2014/04/documentation_v1.8.pdf&#xD;
  [3]: https://www.kaggle.com/c/higgs-boson&#xD;
  [4]: http://opendata.cern.ch/about/ATLAS&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=5393ty56yetjhw4.png&amp;amp;userId=20103&#xD;
  [6]: http://community.wolfram.com//c/portal/getImageAttachment?filename=5256567urytere.png&amp;amp;userId=20103&#xD;
  [7]: http://community.wolfram.com//c/portal/getImageAttachment?filename=rtyee567rutyrd.png&amp;amp;userId=20103&#xD;
  [8]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ghf56utyehw65eyhrw.png&amp;amp;userId=20103</description>
    <dc:creator>Arnoud Buzing</dc:creator>
    <dc:date>2017-02-17T14:16:25Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1647625">
    <title>Sequence-to-sequence regression with recurrent neural networks</title>
    <link>https://community.wolfram.com/groups/-/m/t/1647625</link>
    <description>I recently wanted to learn more about recurrent neural networks (RNNs) and how to use them for regression problems. In particular, I wanted to try and combine RNNs with the ideas for Bayesian error bar estimation I discussed in my blog/community posts a while back:&#xD;
&#xD;
https://blog.wolfram.com/2018/05/31/how-optimistic-do-you-want-to-be-bayesian-neural-network-regression-with-prediction-errors/&#xD;
https://community.wolfram.com/groups/-/m/t/1319745&#xD;
&#xD;
I also found the found the following answer on StackExchange about sequence learning with `SequenceAttentionLayer`, which helped me quite a bit to understand how to use to use these layers:&#xD;
https://mathematica.stackexchange.com/a/143672/43522&#xD;
&#xD;
With those resources in hand, I wanted to give time-series regression a shot.&#xD;
&#xD;
First, let&amp;#039;s use `FinancialData` as an easy source of a test dataset. Here I download 5 years of data from 5 different indices and turn them into a regularly sampled matrix of vectors and then split the dataset into 80/20% training/test data:&#xD;
&#xD;
    indices = {&amp;#034;GOOGL&amp;#034;, &amp;#034;AS:ASML&amp;#034;, &amp;#034;MSFT&amp;#034;, &amp;#034;AAPL&amp;#034;, &amp;#034;GE&amp;#034;};&#xD;
    data = FinancialData[indices, {Today - 5 Quantity[1, &amp;#034;Years&amp;#034;], Today}];&#xD;
    DateListPlot[data]&#xD;
    With[{&#xD;
       matrix = N@Normal[&#xD;
           TimeSeriesRescale[&#xD;
            TimeSeriesResample[TimeSeriesThread[Identity, TimeSeries /@ data]], {0, Max[Length /@ data] - 1}]&#xD;
        ][[All, 2]]&#xD;
      },&#xD;
      {fe, data} = FeatureExtraction[matrix,  &amp;#034;StandardizedVector&amp;#034;, {&amp;#034;ExtractorFunction&amp;#034;, &amp;#034;ExtractedFeatures&amp;#034;}]&#xD;
      ];&#xD;
    {trainingData, testData} = TakeDrop[data, Round[0.8*Length[data]]];&#xD;
    Dimensions /@ {trainingData, testData}&#xD;
&#xD;
![enter image description here][1]&#xD;
&#xD;
Next, we define a function that can generate training data for the network from the data matrix we just made:&#xD;
&#xD;
    Clear[genFun];&#xD;
    genFun[data_, { seqLengthIn_, seqLengthout_, offset_}] := With[{&#xD;
        dim = Dimensions[data][[2]],&#xD;
        max = Max[1, Length[data] - seqLengthout - offset - seqLengthIn - 2]&#xD;
        },&#xD;
       Function[&#xD;
        With[{ri = RandomInteger[{1, max}, #BatchSize]},&#xD;
         &amp;lt;|&#xD;
          &amp;#034;Input&amp;#034; -&amp;gt; Function[data[[# ;; # + seqLengthIn - 1]]] /@ ri,&#xD;
          &amp;#034;Target&amp;#034; -&amp;gt; Join[&#xD;
            ConstantArray[{ConstantArray[0., dim]}, #BatchSize],&#xD;
            Function[With[{j = # + offset + seqLengthIn - 1},   data[[j ;; j + seqLengthout - 1]]]] /@ ri,&#xD;
            2&#xD;
            ]&#xD;
          |&amp;gt;]]];&#xD;
&#xD;
Each time the function is called, it generates a batch of sequences that will be used as training input and target sequences that the network should try to learn and reproduce, but the targets are prepended with a blank start-of-sequence vector:&#xD;
&#xD;
    Dimensions /@ genFun[data, {10, 6, 1}][&amp;lt;|&amp;#034;BatchSize&amp;#034; -&amp;gt; 3|&amp;gt;]&#xD;
    Out[72]= &amp;lt;|&amp;#034;Input&amp;#034; -&amp;gt; {3, 10, 5}, &amp;#034;Target&amp;#034; -&amp;gt; {3, 7, 5}|&amp;gt;&#xD;
    &#xD;
Next we put together our neural network:&#xD;
&#xD;
    Clear[encoderNetAttend, decoderNet, lossLayer, trainingNetAttention];&#xD;
    encoderNetAttend[n_, dropout_] := NetGraph[&amp;lt;|&#xD;
        &amp;#034;lstm&amp;#034; -&amp;gt; LongShortTermMemoryLayer[n, &amp;#034;Dropout&amp;#034; -&amp;gt; dropout], &#xD;
        &amp;#034;last&amp;#034; -&amp;gt; SequenceLastLayer[],&#xD;
        &amp;#034;post&amp;#034; -&amp;gt; &#xD;
         NetChain[{LinearLayer[n], ElementwiseLayer[&amp;#034;SELU&amp;#034;], &#xD;
           DropoutLayer[], LinearLayer[]}]&#xD;
        |&amp;gt;,&#xD;
       {&amp;#034;lstm&amp;#034; -&amp;gt; &amp;#034;last&amp;#034; -&amp;gt; &amp;#034;post&amp;#034; -&amp;gt; NetPort[&amp;#034;StateInit&amp;#034;],  &amp;#034;lstm&amp;#034; -&amp;gt; NetPort[&amp;#034;States&amp;#034;]}&#xD;
       ];&#xD;
    decoderNet[n_, dropout_] := NetGraph[&#xD;
       &amp;lt;|&#xD;
        &amp;#034;part1&amp;#034; -&amp;gt; PartLayer[{All, 1}], &amp;#034;part2&amp;#034; -&amp;gt; PartLayer[{All, 2}],&#xD;
        &amp;#034;lstm&amp;#034; -&amp;gt; LongShortTermMemoryLayer[n, &amp;#034;Dropout&amp;#034; -&amp;gt; dropout],&#xD;
        &amp;#034;shape1&amp;#034; -&amp;gt; ReshapeLayer[{n, 1}],  &amp;#034;shape2&amp;#034; -&amp;gt; ReshapeLayer[{n, 1}], &amp;#034;catState&amp;#034; -&amp;gt; CatenateLayer[2]&#xD;
        |&amp;gt;,&#xD;
       {&#xD;
        NetPort[&amp;#034;Input&amp;#034;] -&amp;gt; NetPort[&amp;#034;lstm&amp;#034;, &amp;#034;Input&amp;#034;], &#xD;
        NetPort[&amp;#034;lstm&amp;#034;, &amp;#034;Output&amp;#034;] -&amp;gt; NetPort[&amp;#034;Output&amp;#034;],&#xD;
        NetPort[&amp;#034;StateIn&amp;#034;] -&amp;gt; &amp;#034;part1&amp;#034; -&amp;gt; NetPort[&amp;#034;lstm&amp;#034;, &amp;#034;State&amp;#034;],&#xD;
        NetPort[&amp;#034;StateIn&amp;#034;] -&amp;gt; &amp;#034;part2&amp;#034; -&amp;gt; NetPort[&amp;#034;lstm&amp;#034;, &amp;#034;CellState&amp;#034;],&#xD;
        NetPort[&amp;#034;lstm&amp;#034;, &amp;#034;State&amp;#034;] -&amp;gt; &amp;#034;shape1&amp;#034;,  NetPort[&amp;#034;lstm&amp;#034;, &amp;#034;CellState&amp;#034;] -&amp;gt; &amp;#034;shape2&amp;#034;,&#xD;
        {&amp;#034;shape1&amp;#034;, &amp;#034;shape2&amp;#034;} -&amp;gt; &amp;#034;catState&amp;#034; -&amp;gt; NetPort[&amp;#034;StateOut&amp;#034;]&#xD;
        },&#xD;
       &amp;#034;StateIn&amp;#034; -&amp;gt; {n, 2}&#xD;
       ];&#xD;
    lossLayer[&amp;#034;LogPrecision&amp;#034;] =  ThreadingLayer@Function[{yObserved, yPredicted, logPrecision},&#xD;
        (yPredicted - yObserved)^2*Exp[logPrecision] - logPrecision&#xD;
        ];&#xD;
    regressionNet[n_, dimIn_, dropout : _?NumericQ : 0.5] := &#xD;
      NetInitialize@NetGraph[&#xD;
        &amp;lt;|&#xD;
         &amp;#034;encoder&amp;#034; -&amp;gt; encoderNetAttend[n, dropout], &#xD;
         &amp;#034;decoder&amp;#034; -&amp;gt; decoderNet[n, dropout],&#xD;
         &amp;#034;attention&amp;#034; -&amp;gt; SequenceAttentionLayer[&amp;#034;Bilinear&amp;#034;], &#xD;
         &amp;#034;catenate&amp;#034; -&amp;gt; CatenateLayer[2],&#xD;
         &amp;#034;regression&amp;#034; -&amp;gt; NetMapOperator[LinearLayer[{2, dimIn}]],&#xD;
         &amp;#034;part1&amp;#034; -&amp;gt; PartLayer[{All, 1}], &amp;#034;part2&amp;#034; -&amp;gt; PartLayer[{All, 2}]&#xD;
         |&amp;gt;,&#xD;
        {&#xD;
         NetPort[&amp;#034;Input&amp;#034;] -&amp;gt; &amp;#034;encoder&amp;#034;,&#xD;
         NetPort[&amp;#034;encoder&amp;#034;, &amp;#034;StateInit&amp;#034;] -&amp;gt; NetPort[&amp;#034;decoder&amp;#034;, &amp;#034;StateIn&amp;#034;],&#xD;
          NetPort[&amp;#034;encoder&amp;#034;, &amp;#034;States&amp;#034;] -&amp;gt; NetPort[&amp;#034;attention&amp;#034;, &amp;#034;Input&amp;#034;],&#xD;
         NetPort[&amp;#034;Prediction&amp;#034;] -&amp;gt; NetPort[&amp;#034;decoder&amp;#034;, &amp;#034;Input&amp;#034;],&#xD;
         NetPort[{&amp;#034;decoder&amp;#034;, &amp;#034;Output&amp;#034;}] -&amp;gt; &#xD;
          NetPort[&amp;#034;attention&amp;#034;, &amp;#034;Query&amp;#034;], {&amp;#034;decoder&amp;#034;, &amp;#034;attention&amp;#034;} -&amp;gt; &#xD;
          &amp;#034;catenate&amp;#034; -&amp;gt; &amp;#034;regression&amp;#034;,&#xD;
         &amp;#034;regression&amp;#034; -&amp;gt; &amp;#034;part1&amp;#034; -&amp;gt; NetPort[&amp;#034;mu&amp;#034;], &#xD;
         &amp;#034;regression&amp;#034; -&amp;gt; &amp;#034;part2&amp;#034; -&amp;gt; NetPort[&amp;#034;logTau&amp;#034;]&#xD;
         },&#xD;
        &amp;#034;Input&amp;#034; -&amp;gt; {&amp;#034;Varying&amp;#034;, dimIn},&#xD;
        &amp;#034;Prediction&amp;#034; -&amp;gt; {&amp;#034;Varying&amp;#034;, dimIn}&#xD;
        ];&#xD;
    trainingNetAttention[n_, dimIn_, dropout : _?NumericQ : 0.5] := NetInitialize@NetGraph[&#xD;
        &amp;lt;|&#xD;
         &amp;#034;regression&amp;#034; -&amp;gt; regressionNet[n, dimIn, dropout],&#xD;
         &amp;#034;loss&amp;#034; -&amp;gt; lossLayer[&amp;#034;LogPrecision&amp;#034;],&#xD;
         &amp;#034;total&amp;#034; -&amp;gt; SummationLayer[],  &amp;#034;most&amp;#034; -&amp;gt; SequenceMostLayer[],  &amp;#034;rest&amp;#034; -&amp;gt; SequenceRestLayer[]&#xD;
         |&amp;gt;,&#xD;
        {&#xD;
         NetPort[&amp;#034;Input&amp;#034;] -&amp;gt; NetPort[&amp;#034;regression&amp;#034;, &amp;#034;Input&amp;#034;],&#xD;
         NetPort[&amp;#034;Target&amp;#034;] -&amp;gt;  &amp;#034;most&amp;#034; -&amp;gt; NetPort[&amp;#034;regression&amp;#034;, &amp;#034;Prediction&amp;#034;],&#xD;
         NetPort[&amp;#034;Target&amp;#034;] -&amp;gt; &amp;#034;rest&amp;#034;,&#xD;
         {&amp;#034;rest&amp;#034;, NetPort[&amp;#034;regression&amp;#034;, &amp;#034;mu&amp;#034;],  NetPort[&amp;#034;regression&amp;#034;, &amp;#034;logTau&amp;#034;]} -&amp;gt; &amp;#034;loss&amp;#034; -&amp;gt; &amp;#034;total&amp;#034; -&amp;gt; NetPort[&amp;#034;Loss&amp;#034;]&#xD;
         },&#xD;
        &amp;#034;Input&amp;#034; -&amp;gt; {&amp;#034;Varying&amp;#034;, dimIn},&#xD;
        &amp;#034;Target&amp;#034; -&amp;gt; {&amp;#034;Varying&amp;#034;, dimIn}&#xD;
        ];&#xD;
    nHidden = 250;&#xD;
    pDrop = 0.25;&#xD;
    NetInformation[encoderNetAttend[nHidden, pDrop], &amp;#034;SummaryGraphic&amp;#034;]&#xD;
    NetInformation[decoderNet[nHidden, pDrop], &amp;#034;SummaryGraphic&amp;#034;]&#xD;
    NetInformation[regressionNet[nHidden, 2, 0.25], &amp;#034;SummaryGraphic&amp;#034;]&#xD;
    NetInformation[ trainingNetAttention[nHidden, 2, 0.25], &amp;#034;SummaryGraphic&amp;#034;]&#xD;
&#xD;
![enter image description here][2]&#xD;
&#xD;
The idea here is that the encoder produces a state vector that the decoder uses to start making predictions. The decoder, in turn, accepts the networks&amp;#039; own predictions to iteratively crank out the next one. During the training, though, we don&amp;#039;t have the actual predictions from the network, so instead we feed in the sequence of actual target values and offset the target sequence at the loss layer by one with a `SequenceRest` layer. This is called *teacher forcing*.&#xD;
&#xD;
Time to train the network:&#xD;
&#xD;
    seqConfig = {15, 7, 1};&#xD;
    trainedTrainObject = NetTrain[&#xD;
       trainingNetAttention[nHidden, Length[indices], pDrop],&#xD;
       genFun[trainingData, seqConfig],&#xD;
       All,&#xD;
       TargetDevice -&amp;gt; &amp;#034;GPU&amp;#034;,  LossFunction -&amp;gt; &amp;#034;Loss&amp;#034;,&#xD;
       TimeGoal -&amp;gt; 30*60, BatchSize -&amp;gt; 200,&#xD;
       ValidationSet -&amp;gt; genFun[testData, seqConfig][&amp;lt;|&amp;#034;BatchSize&amp;#034; -&amp;gt; 200|&amp;gt;]&#xD;
       ];&#xD;
    trainedNet = trainedTrainObject[&amp;#034;TrainedNet&amp;#034;];&#xD;
    trainedTrainObject[&amp;#034;EvolutionPlots&amp;#034;]&#xD;
&#xD;
![enter image description here][3]&#xD;
&#xD;
To make predictions, the network needs to eat its own results iteratively, which we can do with a `NestList`&#xD;
&#xD;
    makePredictorFunction[trainedNet_, evaluationMode : (&amp;#034;Test&amp;#034; | &amp;#034;Train&amp;#034;) : &amp;#034;Test&amp;#034;, device : (&amp;#034;CPU&amp;#034; | &amp;#034;GPU&amp;#034;) : &amp;#034;CPU&amp;#034;] := With[{&#xD;
       dim = Last@NetExtract[trainedNet, {&amp;#034;Input&amp;#034;}],&#xD;
       encoder = NetExtract[trainedNet, {&amp;#034;regression&amp;#034;, &amp;#034;encoder&amp;#034;}],&#xD;
       regressionNet = &#xD;
        NetDelete[NetExtract[trainedNet, &amp;#034;regression&amp;#034;], &amp;#034;encoder&amp;#034;]&#xD;
       },&#xD;
      Function[{input, n},&#xD;
       Module[{&#xD;
         encodedInput = encoder[input, NetEvaluationMode -&amp;gt; evaluationMode, TargetDevice -&amp;gt; device],&#xD;
         vectorInputQ = Depth[input] === 4,&#xD;
         length = Length[input],&#xD;
         reshape&#xD;
         },&#xD;
        reshape = If[vectorInputQ, ConstantArray[#, Length[input]] &amp;amp;, Identity];&#xD;
        GeneralUtilities`AssociationTranspose@NestList[&#xD;
           regressionNet[&#xD;
             &amp;lt;|&amp;#034;Input&amp;#034; -&amp;gt; encodedInput[&amp;#034;States&amp;#034;], &amp;#034;Prediction&amp;#034; -&amp;gt; #mu, &amp;#034;StateIn&amp;#034; -&amp;gt; #StateOut|&amp;gt;,&#xD;
              NetEvaluationMode -&amp;gt; evaluationMode, &#xD;
             TargetDevice -&amp;gt; device] &amp;amp;,&#xD;
           &amp;lt;|&#xD;
            &amp;#034;mu&amp;#034; -&amp;gt; reshape@{ConstantArray[0, dim]},&#xD;
            &amp;#034;StateOut&amp;#034; -&amp;gt; encodedInput[&amp;#034;StateInit&amp;#034;]&#xD;
            |&amp;gt;,&#xD;
           n&#xD;
           ][[2 ;;, {&amp;#034;mu&amp;#034;, &amp;#034;logTau&amp;#034;}, If[vectorInputQ, All, Unevaluated[Sequence[]]], 1]]&#xD;
        ]&#xD;
       ]&#xD;
      ];&#xD;
&#xD;
For example, we can predict 5 steps ahead based on 30 points of historical data:&#xD;
&#xD;
    predictor = makePredictorFunction[trainedNet, &amp;#034;Train&amp;#034;, &amp;#034;CPU&amp;#034;];&#xD;
    Dimensions /@ predictor[data[[;; 30]], 7]&#xD;
&#xD;
    Out[299]= &amp;lt;|&amp;#034;mu&amp;#034; -&amp;gt; {7, 5}, &amp;#034;logTau&amp;#034; -&amp;gt; {7, 5}|&amp;gt;&#xD;
&#xD;
Here&amp;#039;s a manipulate to visualize the predictions against the actual data. We sample the network several times to get a sense of the uncertainty from the training weights and combine that uncertainty with the variance predicted by the network:&#xD;
&#xD;
    Manipulate[&#xD;
     Manipulate[&#xD;
      Quiet@With[{&#xD;
         predictions = Dot[&#xD;
           {{1., 1.}, {1., 0.}, {1., -1.}},&#xD;
           {Mean[#mu], &#xD;
              nstdev*Sqrt[Variance[#mu] + Mean[Exp[-#logTau]]]} &amp;amp;@Map[&#xD;
              Transpose,&#xD;
              predictor[Table[dat[[Max[1, n - t] ;; UpTo[n]]], s], l]&#xD;
              ][[{&amp;#034;mu&amp;#034;, &amp;#034;logTau&amp;#034;}, All, All, index]]&#xD;
           ],&#xD;
         trueData = ListPlot[&#xD;
           MapIndexed[{First[#2] + Max[1, n - t] - 1, #1} &amp;amp;,&#xD;
            Flatten[dat[[Max[1, n - t] ;; UpTo[n + l], index]]]&#xD;
            ],&#xD;
           Joined -&amp;gt; True,&#xD;
           PlotStyle -&amp;gt; Black&#xD;
           ]&#xD;
         },&#xD;
        Show[&#xD;
         ListPlot[&#xD;
          Thread@Legended[&#xD;
            MapIndexed[&#xD;
               {First[#2] + Max[1, n - t] - 1, #1} &amp;amp;,&#xD;
               Flatten[{&#xD;
                 dat[[Max[1, n - t] ;; UpTo[n], index]],&#xD;
                  #&#xD;
                 }]&#xD;
               ] &amp;amp; /@ predictions,&#xD;
            {StringForm[&amp;#034;\[Mu] + `1` \[Sigma]&amp;#034;, Dynamic[nstdev]], &#xD;
             &amp;#034;\[Mu]&amp;#034;, StringForm[&amp;#034;\[Mu] - `1` \[Sigma]&amp;#034;, Dynamic[nstdev]]}&#xD;
            ],&#xD;
          Joined -&amp;gt; True,&#xD;
          PlotStyle -&amp;gt; (Directive[#, Dashed] &amp;amp; /@ {Blue, Red, Blue}),&#xD;
          ImageSize -&amp;gt; 500,&#xD;
          Filling -&amp;gt; {1 -&amp;gt; {2}, 3 -&amp;gt; {2}}&#xD;
          ],&#xD;
         trueData,&#xD;
         ImageSize -&amp;gt; Large,&#xD;
         PlotRange -&amp;gt; All&#xD;
         ]&#xD;
        ],&#xD;
      {{index, 1, &amp;#034;Index&amp;#034;}, Thread[Range[Length[indices]] -&amp;gt; indices]},&#xD;
      {{n, Round[Length[dat]/10], &amp;#034;Position&amp;#034;}, 1, Length[dat], 1},&#xD;
      {{t, 20, &amp;#034;History length&amp;#034;}, 1, 30, 1},&#xD;
      {{l, 30, &amp;#034;Extrapolation&amp;#034;}, 1, 50, 1},&#xD;
      {{s, 5, &amp;#034;Number of samples&amp;#034;}, 1, 20, 1},&#xD;
      {{nstdev, 2, &amp;#034;Standard deviations&amp;#034;}, 0, 4, 0.1},&#xD;
      Paneled -&amp;gt; False,&#xD;
      ContinuousAction -&amp;gt; True,&#xD;
      TrackedSymbols :&amp;gt; {index, n, t, l, s, nstdev},&#xD;
      SynchronousInitialization -&amp;gt; False&#xD;
      ],&#xD;
     {{dat, trainingData, &amp;#034;Dataset&amp;#034;}, {trainingData -&amp;gt; &amp;#034;Training data&amp;#034;, &#xD;
       testData -&amp;gt; &amp;#034;Test data&amp;#034;}},&#xD;
     TrackedSymbols :&amp;gt; {dat},&#xD;
     SynchronousInitialization -&amp;gt; False&#xD;
     ]&#xD;
&#xD;
![enter image description here][4]&#xD;
&#xD;
The results on the validation set do not look great, but the comparison between the first 4 years of the data and the last one may not be fair. Or it may simply be necessary to involve many more indices before it becomes feasible to do extrapolations of this type. At any rate, I hope that this code is useful to other users here! I will probably tweak bits of code here and there over the next few days and maybe add more commentary, so be sure to check back occasionally if you&amp;#039;re interested.&#xD;
&#xD;
**Update**&#xD;
Some of the code needed to be updated slightly to work in the recently released Mathematica V12. The `SequenceAttentionLayer` is being phased out, but still works (see the &amp;#034;Properties &amp;amp; Relations&amp;#034; documentation for `AttentionLayer` for information about how to replace `SequenceAttentionLayer` with `AttentionLayer`). The financial data also needed a few more processing steps in V12 before it can be used. Please see the attached notebook for the V12 version of the code.&#xD;
&#xD;
**Update 2 (10 June 2019)**&#xD;
I attached another notebook with code for a neural network that does not use teacher forcing but instead feeds its own predictions back into itself during training. This makes sure that the network is trained in exactly the same way as it is used afterwards. This also removes the need to use a `NestList` afterwards to generate the predictions. Training the network becomes trickier, though, and you need to experiment more with learning rate multipliers and gradient clipping to get convergence.&#xD;
&#xD;
**Update 3 (13 July 2020)**&#xD;
I just updated the notebooks to make sure that all the code works correctly in Mathematica V12.1&#xD;
&#xD;
To make this code work, you may need to update your neural network paclet first by evaluating:&#xD;
&#xD;
    PacletUpdate[&amp;#034;NeuralNetworks&amp;#034;]&#xD;
&#xD;
  [1]: https://community.wolfram.com//c/portal/getImageAttachment?filename=8936datelistplot.png&amp;amp;userId=839741&#xD;
  [2]: https://community.wolfram.com//c/portal/getImageAttachment?filename=1613networks.png&amp;amp;userId=839741&#xD;
  [3]: https://community.wolfram.com//c/portal/getImageAttachment?filename=progressplot.png&amp;amp;userId=839741&#xD;
  [4]: https://community.wolfram.com//c/portal/getImageAttachment?filename=manipulate.png&amp;amp;userId=839741</description>
    <dc:creator>Sjoerd Smit</dc:creator>
    <dc:date>2019-04-05T15:43:41Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1379001">
    <title>[WSS18] Punctuation Restoration With Recurrent Neural Networks</title>
    <link>https://community.wolfram.com/groups/-/m/t/1379001</link>
    <description># Punctuation Restoration With Recurrent Neural Networks&#xD;
Mengyi Shan, Harvey Mudd College, mshan@hmc.edu        &#xD;
![flow][1]&#xD;
&#xD;
All codes posted on GitHub: [https://github.com/Shanmy/Summer2018Starter/tree/master/Project][2].&#xD;
Raw results in the attached notebook.&#xD;
&#xD;
----------&#xD;
&#xD;
## Introduction&#xD;
In natural language processing problems such as automatic speech recognition (ASR), the generated text is normally unpunctuated, which is hard for further recognition or analysis. Thus punctuation restoration is a small but crucial problem that deserves our attention. This project aims to build an automatic &amp;#034;punctuation adding&amp;#034; tool for plain English text with no punctuation. &#xD;
&#xD;
Since the input text could be considered as a sequence in which context is important for every single word&amp;#039;s properties, recurrent characteristics of neural networks are considered to be a good method. Traditional approaches to this problem include usage of various recurrent neural networks (RNN), especially long short-term memory layers (LSTM). This project examines several models built from different layers and introduces bidirectional operators which can significantly improve the result compared with old methods.&#xD;
&#xD;
## Methods&#xD;
![Basic steps of the method][3]&#xD;
&#xD;
There&amp;#039;re four basic steps in the whole process. First, we get the corpus of articles (with punctuations). Then, we keep the periods and commas in the corpus but change the question marks, exclamation marks, and colons to periods and commas, while removing all other punctuations. With this pure text, we tag each word as one of {NONE, COMMA, PERIOD} by judging if it is followed by a punctuation or not. And this set of tagging rules are sent to a neural network model for training. Finally, we test the result on another piece of articles, which is the test set.&#xD;
&#xD;
### Data&#xD;
Basically, we have two pieces of data. The first one is the Wikipedia text of 4000 nouns (deleting missing), and the second is 50 novels from Wolfram data repository.&#xD;
&#xD;
    (*Get wikipedia text of 4000 nouns*)&#xD;
    nounlist = Select[WordList[], WordData[#, &amp;#034;PartsOfSpeech&amp;#034;][[1]] == &amp;#034;Noun&amp;#034; &amp;amp;];&#xD;
    rawData = StringJoin @@ DeleteCases[Flatten[WikipediaData[#] &amp;amp; /@ Take[nounlist, {1, 4000}], 2], _Missing]&#xD;
&#xD;
    (*Get text of 50 novels*)&#xD;
    books = StringJoin @@ Get /@ ResourceSearch[&amp;#034;novels&amp;#034;, 50];&#xD;
&#xD;
### Pre-processing&#xD;
The first goal of the preprocessing step is to purify the text. That is, since we only consider commas and periods, we should either delete or replace other characters and punctuations. Also, for convenience, all numbers are replaced with 1 first. All other characters are removed from the text.&#xD;
&#xD;
    (*Show sets of characters replaced with comma, period, whitespace, one and null respectively*)&#xD;
    toComma = Characters[&amp;#034;:;&amp;#034;];&#xD;
    toPeriod = Characters[&amp;#034;!?&amp;#034;];&#xD;
    toWhiteSpace = {&amp;#034;-&amp;#034;, &amp;#034;\n&amp;#034;};&#xD;
    toOne = {&amp;#034;0&amp;#034;, &amp;#034;1&amp;#034;, &amp;#034;2&amp;#034;, &amp;#034;3&amp;#034;, &amp;#034;4&amp;#034;, &amp;#034;5&amp;#034;, &amp;#034;6&amp;#034;, &amp;#034;7&amp;#034;, &amp;#034;8&amp;#034;, &amp;#034;9&amp;#034;};&#xD;
    toNull[x_String] := Complement[Union[Characters[x]], ToUpperCase@Alphabet[], Alphabet[], toOne, toComma, toPeriod, toWhiteSpace, {&amp;#034;.&amp;#034;, &amp;#034;,&amp;#034;, &amp;#034; &amp;#034;}];&#xD;
&#xD;
Then complete the replacement and modify it to pure form. And we include a validation test to examine its purity.&#xD;
   &#xD;
    (*Replacement and modification. End with lowercase text with only periods, alphabets and commas.*)&#xD;
    toPureText[x_String] := &#xD;
      StringReplace[#, &amp;#034;.,&amp;#034; .. -&amp;gt; &amp;#034;. &amp;#034;] &amp;amp;@&#xD;
                   StringReplace[#, &amp;#034;. &amp;#034; .. -&amp;gt; &amp;#034;. &amp;#034;] &amp;amp;@&#xD;
                 StringReplace[#, {&amp;#034; ,&amp;#034; -&amp;gt; &amp;#034;,&amp;#034;, &amp;#034; .&amp;#034; -&amp;gt; &amp;#034;.&amp;#034;}] &amp;amp;@&#xD;
               StringReplace[#, {&amp;#034;1&amp;#034; .. -&amp;gt; &amp;#034;one&amp;#034;, &amp;#034; &amp;#034; .. -&amp;gt; &amp;#034; &amp;#034;}] &amp;amp;@&#xD;
             StringReplace[#, {&amp;#034;1. 1&amp;#034; -&amp;gt; &amp;#034;&amp;#034;, &amp;#034;1, 1&amp;#034; -&amp;gt; &amp;#034;1&amp;#034;}] &amp;amp;@&#xD;
           StringReplace[#, {&amp;#034; &amp;#034; .. -&amp;gt; &amp;#034; &amp;#034;}] &amp;amp;@&#xD;
         StringReplace[#, {&amp;#034;,&amp;#034; -&amp;gt; &amp;#034;, &amp;#034;, &amp;#034;.&amp;#034; -&amp;gt; &amp;#034;. &amp;#034;}] &amp;amp;@&#xD;
       ToLowerCase@&#xD;
        StringReplace[{toComma -&amp;gt; &amp;#034;,&amp;#034;, toPeriod -&amp;gt; &amp;#034;.&amp;#034;, toNull[x] -&amp;gt; &amp;#034;&amp;#034;, &#xD;
           toWhiteSpace -&amp;gt; &amp;#034; &amp;#034;, toOne -&amp;gt; &amp;#034;1&amp;#034;}][x];&#xD;
    (*validation test*)&#xD;
    VerificationTest[Length@StringSplit@x == Length@TextWords@x]&#xD;
Then we define a function fPuncTag that can generate the corresponding tagging given a piece of text with punctuation. &#xD;
   &#xD;
    (*Define the tagging function, and maps it to original text. Original text is partitioned into pieces of 200 words*)&#xD;
     fPuncTag := Switch[StringTake[#, -1], &amp;#034;.&amp;#034;, &amp;#034;a&amp;#034;, &amp;#034;,&amp;#034;, &amp;#034;b&amp;#034;, _, &amp;#034;c&amp;#034;] &amp;amp;;&#xD;
     fWordTag[x_String] := Map[fPuncTag, Partition[StringSplit[x], 200], {2}];&#xD;
    &#xD;
And we can thus remove the punctuation, and build a set of rules between the unpunctuated text and the generated tagging.&#xD;
&#xD;
    fWordText[x_String] := StringReplace[#, {&amp;#034;,&amp;#034; -&amp;gt; &amp;#034;&amp;#034;, &amp;#034;.&amp;#034; -&amp;gt; &amp;#034;&amp;#034;}] &amp;amp; /@ StringRiffle /@ Partition[StringSplit[x], 200];&#xD;
    fWordTrain[x_String] := Normal@AssociationThread[fWordText[x], fWordTag[x]];&#xD;
    totalData = fWordTrain@toPureText@rawText&#xD;
&#xD;
With the total data, we want to divide it into three groups: the training set, the validation set, and the test set.&#xD;
&#xD;
    (* First we know that the length is 63252, then we divide it by 15:3:1*)&#xD;
    order = RandomSample[Range[63252]];&#xD;
    trainingSet = totalData[[Take[order, 50000]]];&#xD;
    validationSet = totalData[[Take[order, {50001, 60000}]]];&#xD;
    testSet = totalData[[Take[order, {60001, -1}]]];&#xD;
&#xD;
### Train&#xD;
&#xD;
During neural network training, I used 8 different combinations of layers, out of which 4 are worth considering. They are listed as followed. LSTM layer, gate recurrent layer, and basic recurrent layer are three types of recurrent layers, each representing a net that takes a sequence of vectors and outputs a sequence of the same length. LSTM is commonly used in natural language processing problems, so we start with it as a penetrating point.&#xD;
&#xD;
    (*Pure LSTM*)&#xD;
    net1 = NetChain[{&#xD;
        embeddingLayer,&#xD;
        LongShortTermMemoryLayer[100],&#xD;
        LongShortTermMemoryLayer[60],&#xD;
        LongShortTermMemoryLayer[30],&#xD;
        LongShortTermMemoryLayer[10],&#xD;
        NetMapOperator[LinearLayer[3]], &#xD;
        SoftmaxLayer[&amp;#034;Input&amp;#034; -&amp;gt; {&amp;#034;Varying&amp;#034;, 3}]}, &#xD;
       &amp;#034;Output&amp;#034; -&amp;gt; NetDecoder[{&amp;#034;Class&amp;#034;, {&amp;#034;a&amp;#034;, &amp;#034;b&amp;#034;, &amp;#034;c&amp;#034;}}]&#xD;
       ];&#xD;
&#xD;
    (*Gate Recurrent*)&#xD;
    net2 = NetChain[{&#xD;
        embeddingLayer,&#xD;
        LongShortTermMemoryLayer[100],&#xD;
        GatedRecurrentLayer[60],&#xD;
        LongShortTermMemoryLayer[30],&#xD;
        GatedRecurrentLayer[10],&#xD;
        NetMapOperator[LinearLayer[3]], &#xD;
        SoftmaxLayer[&amp;#034;Input&amp;#034; -&amp;gt; {&amp;#034;Varying&amp;#034;, 3}]}, &#xD;
       &amp;#034;Output&amp;#034; -&amp;gt; NetDecoder[{&amp;#034;Class&amp;#034;, {&amp;#034;a&amp;#034;, &amp;#034;b&amp;#034;, &amp;#034;c&amp;#034;}}]&#xD;
       ];&#xD;
&#xD;
    (Basic Recurrent)&#xD;
    net3 = NetChain[{&#xD;
        embeddingLayer,&#xD;
        LongShortTermMemoryLayer[100],&#xD;
        BasicRecurrentLayer[60],&#xD;
        LongShortTermMemoryLayer[30],&#xD;
        BasicRecurrentLayer[10],&#xD;
        NetMapOperator[LinearLayer[3]], &#xD;
        SoftmaxLayer[&amp;#034;Input&amp;#034; -&amp;gt; {&amp;#034;Varying&amp;#034;, 3}]}, &#xD;
       &amp;#034;Output&amp;#034; -&amp;gt; NetDecoder[{&amp;#034;Class&amp;#034;, {&amp;#034;a&amp;#034;, &amp;#034;b&amp;#034;, &amp;#034;c&amp;#034;}}]&#xD;
       ];&#xD;
&#xD;
    (*Bidirectional*)&#xD;
    net4 = NetChain[{&#xD;
        embeddingLayer,&#xD;
        LongShortTermMemoryLayer[100],&#xD;
        NetBidirectionalOperator[{LongShortTermMemoryLayer[40], &#xD;
          GatedRecurrentLayer[40]}],&#xD;
        NetBidirectionalOperator[{LongShortTermMemoryLayer[20], &#xD;
          GatedRecurrentLayer[20]}],&#xD;
        LongShortTermMemoryLayer[10],&#xD;
        NetMapOperator[LinearLayer[3]], &#xD;
        SoftmaxLayer[&amp;#034;Input&amp;#034; -&amp;gt; {&amp;#034;Varying&amp;#034;, 3}]}, &#xD;
       &amp;#034;Output&amp;#034; -&amp;gt; NetDecoder[{&amp;#034;Class&amp;#034;, {&amp;#034;a&amp;#034;, &amp;#034;b&amp;#034;, &amp;#034;c&amp;#034;}}]&#xD;
       ];&#xD;
&#xD;
The embedding layer is used to change words into vectors that represent their semantic characteristics.&#xD;
&#xD;
    (*The embedding layer here*)&#xD;
    embeddingLayer = NetModel[&amp;#034;GloVe 100-Dimensional Word Vectors Trained on Wikipedia and Gigaword 5 Data&amp;#034;]&#xD;
&#xD;
With all those neural network models set up, we can train each neural network. To save time, I first trained all models with a small data set of only 3 million words to compare their behaviors.&#xD;
&#xD;
    (*train the neural network while saving the training object*)&#xD;
    NetTrain[net, trainingSet, All, ValidationSet -&amp;gt; validationSet]&#xD;
### Test&#xD;
Since this classification problem is a problem of a skewed dataset, that is, most of the words should have the tag &amp;#034;None&amp;#034;, it doesn&amp;#039;t make sense to use &amp;#034;accuracy&amp;#034; to measure the models&amp;#039; behavior. Even if it simply do nothing and always return &amp;#034;None&amp;#034;, it will have a high accuracy that is the percentage of &amp;#034;None&amp;#034; in the whole tagging set. Instead, to evaluate the behavior of the models, we introduce the concept of precision, recall, and f1-score.&#xD;
&#xD;
    (*Precision and recall*)&#xD;
    precision = truePrediction/allTrue&#xD;
    recall = truePrediction/allPrediction&#xD;
    F1 = HarmonicMean[{precision, recall}]&#xD;
&#xD;
![PR][4]&#xD;
&#xD;
For a given test set, first, we want to remove its punctuations and run the trained model on it. &#xD;
&#xD;
    (*romve punctuation and run the model*)&#xD;
    noPuncTest = Keys /@ testSet&#xD;
    result = net[&amp;#034;TrainedNet&amp;#034;] /@ noPuncTest;&#xD;
    &#xD;
Then we changed the tags to 1,2 and 0. And we calculate the elementwise product of realTag and resultTag. If an element is 4, it means that both the realTag and resultTag is 2, which counts as a successful prediction of a comma. An element of 2 represents a successful prediction of a period.&#xD;
&#xD;
![Tag][5]&#xD;
&#xD;
&#xD;
    (*Change the tags to numerical values and count 1s and 4s*)&#xD;
    realTag = Replace[Flatten[Values /@ Take[testSet, 3252]], {&amp;#034;a&amp;#034; -&amp;gt; 1, &amp;#034;b&amp;#034; -&amp;gt; 2, &amp;#034;c&amp;#034; -&amp;gt; 0}, {1}];&#xD;
    resultTag = Replace[Flatten[result], {&amp;#034;a&amp;#034; -&amp;gt; 1, &amp;#034;b&amp;#034; -&amp;gt; 2, &amp;#034;c&amp;#034; -&amp;gt; 0}, {1}];&#xD;
    totalTag = realTag*resultTag;&#xD;
&#xD;
Now we can use totalTag, resultTag, and realTag to calculate precision, recall, and f1-score.&#xD;
&#xD;
    (*Precision*)&#xD;
    PrecPeriod = N@Count[totalTag, 1]/Count[resultTag, 1]&#xD;
    PrecComma = N@Count[totalTag, 4]/Count[resultTag, 2]&#xD;
    (*Recall*)&#xD;
    RecPeriod = N@Count[totalTag, 1]/Count[realTag, 1]&#xD;
    RecComma = N@Count[totalTag, 4]/Count[realTag, 2]&#xD;
    (*F1*)&#xD;
    F1Period = (2*RecPeriod*PrecPeriod)/(RecPeriod + PrecPeriod)&#xD;
    F1Comma = (2*RecComma*PrecComma)/(RecComma + PrecComma)&#xD;
&#xD;
## Result&#xD;
Ten neural networks are trained based on a small dataset with different layers. Only using Long Short-Term Memory layers gives an f1 score of 13% and 11% for periods and commas. Introducing dropout parameters, pooling layers, elementwise layers, basic recurrent layers and gate recurrent layers all produce an f1 score between 10% and 30%, showing no significant improvement. Introduction of the bidirectional operator (combining two recurrent layers) improves the scores to 53% and 47%, and to 72% and 60% respectively when training on a larger dataset of 10M words.&#xD;
&#xD;
 Here are the results for the three different neural networks trained with a 3M small dataset, and bidirectional neural network (which has the best performance in the small dataset) trained with a larger dataset of 10M words. The first figure is of the period and the second is of the comma.&#xD;
![Period][6]&#xD;
![Comma][7]&#xD;
&#xD;
We can easily observe the advantage of the bidirectional operator in terms of both periods and commas, precision and recall. Instead of the sequence to sequence learning, &amp;#034;tagging&amp;#034; is a significantly more efficient and accurate way to restore punctuation in plain text. Since every words&amp;#039; tags (&amp;#034;None&amp;#034;, &amp;#034;Comma&amp;#034;, &amp;#034;Period&amp;#034;) is influenced by its context, it makes sense that recurrent neural networks and bidirectional operators show great potential in this research.&#xD;
&#xD;
Generally, the recall score is significantly lower than the precision score, suggesting that the model generates too many punctuations than it should. This could be due to the dataset of Wikipedia which is not clean enough. In the Wikipedia text, sometimes there&amp;#039;re equations, translations, or other strange characters that we simply delete. This changed the ratio of punctuations to words and produces some segments of text that is &amp;#034;full of&amp;#034; punctuations since all words are not recognized and simply deleted. One example of those &amp;#034;not clean segment&amp;#034; is shown below.&#xD;
&#xD;
![wiki][8]&#xD;
&#xD;
Also, the overall performance on commas is slightly worse than on periods. This also makes sense from a linguistics point of view. There seems to be a concrete linguistics set of rules for the period, but the usage of comma greatly depends on personal writing style. For example, you could say either *&amp;#034;I like apples but I don&amp;#039;t like bananas.&amp;#034;*, or *&amp;#034;I like apples, but I don&amp;#039;t like bananas.&amp;#034;* In this way, it&amp;#039;s really hard to build a model for comma prediction with such high accuracy. But fortunately, sometimes adding commas or not doesn&amp;#039;t really influence the overall meaning of the sentence. So it&amp;#039;s okay to be tolerant to a slightly worse performance on commas.&#xD;
&#xD;
## Future Works&#xD;
70% f1-score is still not enough for the application. Planned future work focuses on improving accuracy to a level suitable for usage in industry. The most urgent and important future work is using a larger data size. We can observe great improvement when changing from 3M to 10M dataset, but it&amp;#039;s still far less than enough. &#xD;
&#xD;
![plot][9]&#xD;
&#xD;
If we take a closer look at the evolution plots during training, we can see that the error rate and loss of training set are continuously decreasing, while the error rate and loss of the validation set soon reaches a stable state and doesn&amp;#039;t change too much. The gap between those two curves suggests the possibility of overfitting, and it should greatly help if we introduce better and more data.&#xD;
&#xD;
Also, punctuation restoration should not be limited to periods and comma. A more rigorous study of the question mark, exclamation mark, colon, and quotation mark is expected. However, we should note that the choice of most punctuations is not restricted to one possibility. In cases like distinguishing a period with an exclamation mark, we cannot expect a high f1-score. But it&amp;#039;s still an interesting topic, may be useful for topics like sentimental analysis.&#xD;
&#xD;
## Acknowledgement&#xD;
I would like to thank the summer school for providing the environment and background skills for me to finish this project. Especially, I want to thank my mentor for helping me with neural network problems and debugging.&#xD;
&#xD;
## Data and Reference&#xD;
&#xD;
 - [Wolfram Data Repository][10]&#xD;
 - [Wikipedia][11]&#xD;
 - Tilk O, et al. &amp;#034;Lstm for Punctuation Restoration in Speech Transcripts.&amp;#034; Proceedings of the Annual Conference of the International Speech Communication Association, Interspeech, 2015-January, 2015, pp. 683\687.&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-10at7.10.22PM.png&amp;amp;userId=1362824&#xD;
  [2]: https://github.com/Shanmy/Summer2018Starter/tree/master/Project&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-11at10.22.30AM.png&amp;amp;userId=1362824&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=PR1.png&amp;amp;userId=1362824&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-11at11.45.44AM.png&amp;amp;userId=1362824&#xD;
  [6]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-10at8.38.40PM.png&amp;amp;userId=1362824&#xD;
  [7]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-10at8.38.49PM.png&amp;amp;userId=1362824&#xD;
  [8]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-11at12.13.54PM.png&amp;amp;userId=1362824&#xD;
  [9]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-10at8.59.14PM.png&amp;amp;userId=1362824&#xD;
  [10]: https://datarepository.wolframcloud.com/category/Text-Literature/&#xD;
  [11]: https://www.wikipedia.org</description>
    <dc:creator>Mengyi Shan</dc:creator>
    <dc:date>2018-07-11T17:20:45Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1732586">
    <title>[WSC19] Mood Detection in Human Speech</title>
    <link>https://community.wolfram.com/groups/-/m/t/1732586</link>
    <description>![Feature Space Plot for speech data][1]&#xD;
&#xD;
### *Figure Above: Feature Space Plot for speech data*&#xD;
&#xD;
&#xD;
----------&#xD;
&#xD;
&#xD;
## Abstract&#xD;
In this project, I aim to design a system which is capable of detecting mood in human speech. Specifically, the system can be trained on a single user&amp;#039;s voice given samples of emotional speech labeled as being angry, happy, or sad. The system is then able to classify future audio clips of the user&amp;#039;s speech as having one of these three moods. I collected voice samples of myself and trained a Classifier Function based on this data. I experimented with many different available methods for the Classifier Function and for audio preprocessing to obtain the most accurate Classifier.&#xD;
&#xD;
## Obtaining Data&#xD;
In this project, I focused on detecting mood for only one user (specifically, myself) since different people may express mood in different ways, leading to confusion for the Classifier. I initially recorded ten speech clips in each mood as training data, and ten different clips in each mood as testing data. I used [Audacity](https://www.audacityteam.org/) to record audio clips in 32-bit floating point resolution, exported as WAV files. If you&amp;#039;re looking to replicate this project, you can use your own data, or use mine, available on [my GitHub repository](https://github.com/vedadehhc/MoodDetector). I later recorded additional clips, as discussed below.&#xD;
&#xD;
## Feature Extraction&#xD;
In order to produce the most accurate Classifier, I extracted features which I thought were most useful to detecting mood. Specifically, I extracted the amplitudes, fundamental frequencies, and formant frequencies of each clip over the length of the clip using [AudioLocalMeasurements](https://reference.wolfram.com/language/ref/AudioLocalMeasurements.html). That is, I took multiple measurements of each of these values, over many partitions of the clip. I partitioned each clip into 75 parts, but feel free to experiment with different values. I also found the word rate, using Wolfram Language&amp;#039;s experimental [SpeechRecognize](https://reference.wolfram.com/language/ref/SpeechRecognize.html) function, and the ratio of pausing time to total time of the clip using [AudioIntervals](https://reference.wolfram.com/language/ref/AudioIntervals.html). The final function takes the location of the audio file (could be local or on the web) and the number of partitions, and returns an association with the extracted features. It&amp;#039;s important that the function return an association, since this makes things much easier when constructing the Classifier Function. The initial function for feature extraction is included below.&#xD;
&#xD;
    extractFeatures[fileLocation_, parts_] :=  &#xD;
     Module[{audio, assoc, pdur, amp, freq, form}, &#xD;
      audio = Import[fileLocation];&#xD;
      pdur = AudioMeasurements[audio, &amp;#034;Duration&amp;#034;]/parts;&#xD;
      amp = AudioLocalMeasurements[audio, &amp;#034;RMSAmplitude&amp;#034;, &#xD;
         PartitionGranularity -&amp;gt; pdur] // Normal;&#xD;
      freq = AudioLocalMeasurements[audio, &amp;#034;FundamentalFrequency&amp;#034;, &#xD;
         MissingDataMethod -&amp;gt; {&amp;#034;Interpolation&amp;#034;, InterpolationOrder -&amp;gt; 1}, &#xD;
         PartitionGranularity -&amp;gt; pdur] // Normal;&#xD;
      form =  &#xD;
       AudioLocalMeasurements[audio, &amp;#034;Formants&amp;#034;, &#xD;
         PartitionGranularity -&amp;gt; pdur] // Normal;&#xD;
      assoc = &amp;lt;|&#xD;
        Table[&amp;#034;amplitude&amp;#034; &amp;lt;&amp;gt; ToString[i] -&amp;gt; amp[[i]][[2]], {i, Length[amp]}], &#xD;
        Table[&amp;#034;frequency&amp;#034; &amp;lt;&amp;gt; ToString[i] -&amp;gt; freq[[i]][[2]], {i, Length[freq]}], &#xD;
        &amp;#034;wordrate&amp;#034; -&amp;gt; &#xD;
          Length[TextWords[Quiet[SpeechRecognize[audio]]]]/&#xD;
          AudioMeasurements[audio, &amp;#034;Duration&amp;#034;],&#xD;
        Table[Table[&amp;#034;formant&amp;#034; &amp;lt;&amp;gt; ToString[i] &amp;lt;&amp;gt; &amp;#034;-&amp;#034; &amp;lt;&amp;gt; ToString[j] -&amp;gt;&#xD;
          form[[i]][[j]], {j, Length[form[[i]]]}], {i, Length[form]}],&#xD;
        &amp;#034;pauses&amp;#034; -&amp;gt;  &#xD;
          Total[Abs /@ Subtract @@@ AudioIntervals[audio, &amp;#034;Quiet&amp;#034;]]/&#xD;
          AudioMeasurements[audio, &amp;#034;Duration&amp;#034;]&#xD;
        |&amp;gt;; &#xD;
      Map[Normal, assoc, {1}]&#xD;
    ]&#xD;
&#xD;
### Get Training Data&#xD;
Using this function, I was able get the features for all of my training data. Here, I&amp;#039;ll import my data from [my GitHub repository](https://github.com/vedadehhc/MoodDetector).&#xD;
&#xD;
    angryTrainingFeats = &#xD;
     Table[extractFeatures[&#xD;
       &amp;#034;https://github.com/vedadehhc/MoodDetector/raw/master/AudioData/&#xD;
        TrainingData/angry&amp;#034; &amp;lt;&amp;gt; ToString[i] &amp;lt;&amp;gt; &amp;#034;.wav&amp;#034;, 75], {i, 10}];&#xD;
    happyTrainingFeats = &#xD;
     Table[extractFeatures[&#xD;
       &amp;#034;https://github.com/vedadehhc/MoodDetector/raw/master/AudioData/&#xD;
       TrainingData/happy&amp;#034; &amp;lt;&amp;gt; ToString[i] &amp;lt;&amp;gt; &amp;#034;.wav&amp;#034;, 75], {i, 10}];&#xD;
    sadTrainingFeats = &#xD;
     Table[extractFeatures[&#xD;
       &amp;#034;https://github.com/vedadehhc/MoodDetector/raw/master/AudioData/&#xD;
       TrainingData/sad&amp;#034; &amp;lt;&amp;gt; ToString[i] &amp;lt;&amp;gt; &amp;#034;.wav&amp;#034;, 75], {i, 10}];&#xD;
&#xD;
### Get Testing Data&#xD;
I also imported my testing data in the same way, so that it could be passed as an argument to the Classifier Function. I&amp;#039;ll get this from GitHub as well. Note that this is the regular test data on GitHub.&#xD;
&#xD;
    angryTestingFeats =  &#xD;
     Table[extractFeatures[&#xD;
       &amp;#034;https://github.com/vedadehhc/MoodDetector/raw/master/AudioData/&#xD;
       TestingData/Regular/a&amp;#034; &amp;lt;&amp;gt; ToString[i] &amp;lt;&amp;gt; &amp;#034;.wav&amp;#034;, 75], {i, 10}];&#xD;
    happyTestingFeats =  &#xD;
     Table[extractFeatures[&#xD;
       &amp;#034;https://github.com/vedadehhc/MoodDetector/raw/master/AudioData/&#xD;
       TestingData/Regular/h&amp;#034; &amp;lt;&amp;gt; ToString[i] &amp;lt;&amp;gt; &amp;#034;.wav&amp;#034;, 75], {i, 10}];&#xD;
    sadTestingFeats =  &#xD;
     Table[extractFeatures[&#xD;
       &amp;#034;https://github.com/vedadehhc/MoodDetector/raw/master/AudioData/&#xD;
       TestingData/Regular/s&amp;#034; &amp;lt;&amp;gt; ToString[i] &amp;lt;&amp;gt; &amp;#034;.wav&amp;#034;, 75], {i, 10}];&#xD;
&#xD;
## Training a Classifier&#xD;
I constructed a Classifier Function using [Classify](https://reference.wolfram.com/language/ref/Classify.html).&#xD;
&#xD;
    classifier = &#xD;
     Classify[&amp;lt;|&amp;#034;angry&amp;#034; -&amp;gt; angryTrainingFeats, &#xD;
       &amp;#034;happy&amp;#034; -&amp;gt; happyTrainingFeats, &amp;#034;sad&amp;#034; -&amp;gt; sadTrainingFeats|&amp;gt;, &#xD;
      Method -&amp;gt; &amp;#034;LogisticRegression&amp;#034;]&#xD;
&#xD;
I ran the classifier on each set of training data.&#xD;
&#xD;
    classifier[angryTrainingFeats]&#xD;
    classifier[happyTrainingFeats]&#xD;
    classifier[sadTrainingFeats]&#xD;
&#xD;
I experimented with all of the built-in options for [Method](https://reference.wolfram.com/language/ref/Method.html) to construct a Classifier Function with the best accuracy. I found that [LogisticRegression](https://reference.wolfram.com/language/ref/method/LogisticRegression.html) gave the best accuracy at 77% accuracy on the test data. However, I wanted to improve the accuracy further.&#xD;
&#xD;
## Audio Pre-Processing&#xD;
One of the things that improved the Classifier&amp;#039;s accuracy substantially was cleaning the audio before extracting features and classifying. Specifically, I trimmed the audio using [AudioTrim](https://reference.wolfram.com/language/ref/AudioTrim.html), and filtered each clip using [HighpassFilter](https://reference.wolfram.com/language/ref/HighpassFilter.html) before extracting features. The audio cleaning function is included below.&#xD;
&#xD;
    cleanAudio[fileLocation_] := Module[{audio, trimmed, filtered},&#xD;
      audio = Import[fileLocation];&#xD;
      trimmed = AudioTrim[audio];&#xD;
      filtered = HighpassFilter[trimmed, Quantity[300, &amp;#034;Hertz&amp;#034;]]&#xD;
    ]&#xD;
&#xD;
### New Feature Extraction Function&#xD;
I updated the feature extraction function to include audio cleaning.&#xD;
&#xD;
    extractCleanFeatures[fileLocation_, parts_] :=  &#xD;
     Module[{audio, assoc, pdur, amp, freq, form}, &#xD;
      audio = cleanAudio[fileLocation];&#xD;
      pdur = AudioMeasurements[audio, &amp;#034;Duration&amp;#034;]/parts;&#xD;
      amp = AudioLocalMeasurements[audio, &amp;#034;RMSAmplitude&amp;#034;, &#xD;
         PartitionGranularity -&amp;gt; pdur] // Normal;&#xD;
      freq = AudioLocalMeasurements[audio, &amp;#034;FundamentalFrequency&amp;#034;, &#xD;
         MissingDataMethod -&amp;gt; {&amp;#034;Interpolation&amp;#034;, InterpolationOrder -&amp;gt; 1}, &#xD;
         PartitionGranularity -&amp;gt; pdur] // Normal;&#xD;
      form =  &#xD;
       AudioLocalMeasurements[audio, &amp;#034;Formants&amp;#034;, &#xD;
         PartitionGranularity -&amp;gt; pdur] // Normal;&#xD;
      assoc = &amp;lt;|&#xD;
        Table[&#xD;
         &amp;#034;amplitude&amp;#034; &amp;lt;&amp;gt; ToString[i] -&amp;gt; amp[[i]][[2]], {i, Length[amp]}], &#xD;
        Table[&#xD;
         &amp;#034;frequency&amp;#034; &amp;lt;&amp;gt; ToString[i] -&amp;gt; freq[[i]][[2]], {i, Length[freq]}], &#xD;
        &amp;#034;wordrate&amp;#034; -&amp;gt; &#xD;
         Length[TextWords[Quiet[SpeechRecognize[audio]]]]/&#xD;
          AudioMeasurements[audio, &amp;#034;Duration&amp;#034;],&#xD;
        Table[&#xD;
         Table[&amp;#034;formant&amp;#034; &amp;lt;&amp;gt; ToString[i] &amp;lt;&amp;gt; &amp;#034;-&amp;#034; &amp;lt;&amp;gt; ToString[j] -&amp;gt; &#xD;
           form[[i]][[j]], {j, Length[form[[i]]]}], {i, Length[form]}],&#xD;
        &amp;#034;pauses&amp;#034; -&amp;gt;  &#xD;
         Total[Abs /@ Subtract @@@ AudioIntervals[audio, &amp;#034;Quiet&amp;#034;]]/&#xD;
          AudioMeasurements[audio, &amp;#034;Duration&amp;#034;]&#xD;
        |&amp;gt;; &#xD;
      Map[Normal, assoc, {1}]&#xD;
    ]&#xD;
&#xD;
### New Results&#xD;
Using audio cleaning, the accuracy of the classifier improved to 90%, much better than before. The results can be seen in the Confusion Matrix Plot below, generated using [ClassifierMeasurements](https://reference.wolfram.com/language/ref/ClassifierMeasurements.html).&#xD;
&#xD;
![Confusion Matrix Plot for Regular Data][2]&#xD;
&#xD;
## Testing with Neutral Statements&#xD;
Now, up until now, the statements used for recordings were all emotional in nature. For example, the clips recorded in an angry mood also had an angry statement being said. In order to control for this, I recorded neutral statements in each mood. That is, I recorded each of ten emotionally neutral statements in each of the three moods. If the Classifier still works on this data, that would show that it is not relying on the content of the speech, but on other audio features, which is the intended method. I imported these data using the clean feature extractor and, once again, I&amp;#039;ll download them from my GitHub here. Note that this is the Neutral Statements data.&#xD;
&#xD;
    nAngryCleanTestingFeats =  &#xD;
      Table[extractCleanFeatures[&#xD;
        &amp;#034;https://github.com/vedadehhc/MoodDetector/raw/master/AudioData/&#xD;
        TestingData/NeutralStatements/a&amp;#034; &amp;lt;&amp;gt; ToString[i] &amp;lt;&amp;gt; &amp;#034;.wav&amp;#034;, 75], {i, &#xD;
        10}];&#xD;
    nHappyCleanTestingFeats =  &#xD;
     Table[extractCleanFeatures[&#xD;
       &amp;#034;https://github.com/vedadehhc/MoodDetector/raw/master/AudioData/&#xD;
       TestingData/NeutralStatements/h&amp;#034; &amp;lt;&amp;gt; ToString[i] &amp;lt;&amp;gt; &amp;#034;.wav&amp;#034;, 75], {i, &#xD;
       10}];&#xD;
    nSadCleanTestingFeats =  &#xD;
     Table[extractCleanFeatures[&#xD;
       &amp;#034;https://github.com/vedadehhc/MoodDetector/raw/master/AudioData/&#xD;
       TestingData/NeutralStatements/s&amp;#034; &amp;lt;&amp;gt; ToString[i] &amp;lt;&amp;gt; &amp;#034;.wav&amp;#034;, 75], {i, &#xD;
       10}];&#xD;
&#xD;
### Results for Neutral Statements&#xD;
I ran the clean Classifier on the new data, and the results were very positive. The classifier achieved an accuracy of 97% on the Neutral Statements data. The results are displayed in the Confusion Matrix Plot below, generated using [ClassifierMeasurements](https://reference.wolfram.com/language/ref/ClassifierMeasurements.html).&#xD;
&#xD;
![Confusion Matrix Plot for Neutral Statements Data][3]&#xD;
&#xD;
## Conclusions&#xD;
Overall, the Classifier was able to identify mood at 93% accuracy, even when the same statements were spoken in different moods. The composite Confusion Matrix Plot for all testing data can be seen below.&#xD;
&#xD;
![Confusion Matrix Plot for all test data][4]&#xD;
&#xD;
## Future Work&#xD;
In the future, I hope to improve the accuracy of the Classifier by providing additional training data, and to test it further with additional testing data. I also hope to expand the range of moods that the Classifier handles, including moods such as fear, calmness, and excitement. This, of course, would require the aforementioned additional data, and perhaps, more complex structures for the Classifier Function. In the future I would also like to experiment with multiple speakers, and determine whether classifiers for one speaker&amp;#039;s moods can be used to determine those of another speaker.&#xD;
&#xD;
## Acknowledgements&#xD;
I would like to thank my mentor Faizon Zaman for his guidance and assistance on this project.&#xD;
&#xD;
## GitHub&#xD;
You can find my code for this project on [my GitHub repository](https://github.com/vedadehhc/MoodDetector), with all code available beginning July 12th, 2019.&#xD;
&#xD;
  [1]: https://community.wolfram.com//c/portal/getImageAttachment?filename=featureSpacePlotNoLabel.png&amp;amp;userId=1724789&#xD;
  [2]: https://community.wolfram.com//c/portal/getImageAttachment?filename=CMP1.png&amp;amp;userId=1724789&#xD;
  [3]: https://community.wolfram.com//c/portal/getImageAttachment?filename=CMP2.png&amp;amp;userId=1724789&#xD;
  [4]: https://community.wolfram.com//c/portal/getImageAttachment?filename=CMP3.png&amp;amp;userId=1724789</description>
    <dc:creator>Dev Chheda</dc:creator>
    <dc:date>2019-07-12T01:16:42Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1383518">
    <title>[WSC18] Music Sentiment Analysis through Machine Learning</title>
    <link>https://community.wolfram.com/groups/-/m/t/1383518</link>
    <description>![A Representation of the emotion categorization system][1]&#xD;
&#xD;
&#xD;
----------&#xD;
&#xD;
&#xD;
#Abstract&#xD;
This project aims to develop a machine learning application to identify the sentiments in a music clip. The data set I used consists of one hundred 45-second clips from the Database for Emotional Analysis of Music and an additional 103 gathered by myself. I manually labeled all 203 clips and used them as training data for my program. This program works best with classical-style music, which is the main component of my data set, but also works with other genres to an reasonable extent. &#xD;
&#xD;
#Introduction&#xD;
One of the most important functions of music is to affect emotion, but the experience of emotion is ambiguous and subjective to individual. The same music may induce a diverse range of feelings in people as a result of different context, personality, or culture. Many musical features, however, usually lead to the same effect on the human brain. For example, louder music correlates more with excitement or anger, while softer music corresponds to tenderness. This consistency makes it possible to train a supervised machine learning program based on musical features.&#xD;
&#xD;
#Background&#xD;
This project is based on James Russell&amp;#039;s circumplex model, in which a two-dimensional emotion space is constructed from the x-axis of valence level and y-axis of arousal level, as shown above in the picture. Specifically, valence is a measurement of an emotion&amp;#039;s pleasantness, whereas arousal is a measurement of an emotion&amp;#039;s intensity. Russell&amp;#039;s model provides a metric on which different sentiments can be compared and contrasted, creating four main categories of emotion: Happy (high valence, high arousal), Stressed (low valence, high arousal), Sad (low valence, low arousal), and Calm (high valence, low arousal). Within these main categories there are various sub-categories, labeled on the graph above. Notably, &amp;#034;passionate&amp;#034; is a sub-category that does not belong to any main category due to its ambiguous valence value. &#xD;
&#xD;
&#xD;
----------&#xD;
&#xD;
&#xD;
#Program Structure&#xD;
The program contains a three-layer structure. The first layer is responsible for extracting musical features, the second for generating a list of numerical predictions based on different features, and the third for predicting and displaying the most probable emotion descriptors based on the second layer&amp;#039;s output.  &#xD;
![enter image description here][2]&#xD;
&#xD;
##First Layer&#xD;
&#xD;
The first layer consists of 23 feature extractors that generate numerical sequence based on different features:&#xD;
&#xD;
    (*A list of feature extractors*)&#xD;
    feMin[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;Min&amp;#034;, List]]&#xD;
    feMax[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;Max&amp;#034;, List]]&#xD;
    feMean[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;Mean&amp;#034;, List]]&#xD;
    feMedian[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;Median&amp;#034;, List]]&#xD;
    fePower[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;Power&amp;#034;, List]]&#xD;
    feRMSA[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;RMSAmplitude&amp;#034;, List]]&#xD;
    feLoud[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;Loudness&amp;#034;, List]]&#xD;
    feCrest[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;CrestFactor&amp;#034;, List]]&#xD;
    feEntropy[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;Entropy&amp;#034;, List]]&#xD;
    fePeak[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;PeakToAveragePowerRatio&amp;#034;, List]]&#xD;
    feTCent[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;TemporalCentroid&amp;#034;, List]]&#xD;
    feZeroR[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;ZeroCrossingRate&amp;#034;, List]]&#xD;
    feForm[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;Formants&amp;#034;, List]]&#xD;
    feHighFC[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;HighFrequencyContent&amp;#034;, List]]&#xD;
    feMFCC[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;MFCC&amp;#034;, List]]&#xD;
    feSCent[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;SpectralCentroid&amp;#034;, List]]&#xD;
    feSCrest[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;SpectralCrest&amp;#034;, List]]&#xD;
    feSFlat[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;SpectralFlatness&amp;#034;, List]]&#xD;
    feSKurt[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;SpectralKurtosis&amp;#034;, List]]&#xD;
    feSRoll[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;SpectralRollOff&amp;#034;, List]]&#xD;
    feSSkew[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;SpectralSkewness&amp;#034;, List]]&#xD;
    feSSlope[audio_] :=  Normal[AudioLocalMeasurements[audio, &amp;#034;SpectralSlope&amp;#034;, List]]&#xD;
    feSSpread[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;SpectralSpread&amp;#034;, List]]&#xD;
    feNovelty[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;Novelty&amp;#034;, List]]&#xD;
&amp;lt;br/&amp;gt;&#xD;
##Second Layer&#xD;
Using data generated from the first layer, the valence and arousal predictors of the second layer provide 46 predictions for the audio input, based on its different features. &#xD;
&#xD;
    (*RMSAmplitude*)&#xD;
    (*Feature extractor*) feRMSA[audio_] := Normal[AudioLocalMeasurements[audio, &amp;#034;RMSAmplitude&amp;#034;, List]]&#xD;
    dataRMSA = Table[First[takeLast[feRMSA[First[Take[musicFiles, {n}]]]]], {n, Length[musicFiles]}];&#xD;
    (*Generating predictor*) pArousalRMSA = Predict[dataRMSA -&amp;gt; arousalValueC]&#xD;
![Sample predictor function][3]&#xD;
&#xD;
&amp;lt;br/&amp;gt;&#xD;
##Third Layer&#xD;
The two parts of the third layer, main category classifier and sub-category classifier, each utilize the tensors generated in the second layer to make a prediction within their realm of emotion. The output consists of two parts, a main category emotion and a sub-category emotion.&#xD;
&#xD;
    (*Main*) emotionClassify1 = Classify[classifyMaterial -&amp;gt; emotionList1, PerformanceGoal -&amp;gt; &amp;#034;Quality&amp;#034;]&#xD;
    (*Sub*) emotionClassify2 = Classify[classifyMaterial -&amp;gt; emotionList2, PerformanceGoal -&amp;gt; &amp;#034;Quality&amp;#034;]&#xD;
![enter image description here][4]&#xD;
&#xD;
&amp;lt;br/&amp;gt;&#xD;
##Output&#xD;
If the program receives an input that is longer than 45 second, it will automatically clip the audio file into 45 second segments and return the result for each. If the last segment is less than 45 seconds, the program would still work fine on it, though with reduced accuracy. The display for each clip includes a main-category and a sub-category descriptor, with each of their associated probability also printed. &#xD;
&#xD;
###Sample testing: Debussy&amp;#039;s Clair de Lune&#xD;
![enter image description here][5]&#xD;
&#xD;
&amp;lt;br/&amp;gt;&#xD;
&#xD;
----------&#xD;
&#xD;
&#xD;
#Conclusion&#xD;
The program gives very reasonable result for most music in the classical style. However, the program have three shortcomings that I plan to fix in later versions of the this program. Firstly, the program may give contradictory result (ex. happy and depressed) if the sentiment dramatically changes in the middle of a 45 second segment, perhaps reflecting the music&amp;#039;s changing emotional composition. The current 45 second clipping window is rather long and thus prone to capture contradicting emotions. In the next version of this program, the window will probably be shortened to 30 or 20 seconds to reduce prediction uncertainty. Secondly, the program&amp;#039;s processing speed has a lot of room of improvement. It currently takes about one and half minutes to compute an one minute audio file. In future versions I will remove relative ineffective feature extractors to speed things up. Lastly, the data used in creating this application is solely from myself, and therefore it is prone to my human biases. I plan to expand the data set with more people&amp;#039;s input and more genres of music. &#xD;
&#xD;
I have attached the application to this post so that everyone can try out the program.&#xD;
&#xD;
#Acknowledgement&#xD;
I sincerely thank my mentor, Professor Rob Morris, for providing invaluable guidance to help me carry out the project. I also want to thank Rick Hennigan for giving me crucial support with my code. &#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=8714Emotion2DSpace.PNG&amp;amp;userId=1371765&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=2406DataStructure.PNG&amp;amp;userId=1371765&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=8990capture1.PNG&amp;amp;userId=1371765&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=5765capture2.PNG&amp;amp;userId=1371765&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=3607SampleTesting.PNG&amp;amp;userId=1371765</description>
    <dc:creator>William Yicheng Zhu</dc:creator>
    <dc:date>2018-07-14T02:40:20Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/3394441">
    <title>Wolfram Language for biosciences research and teaching</title>
    <link>https://community.wolfram.com/groups/-/m/t/3394441</link>
    <description>[![Wolfram Language for biosciences research and teaching][2]][1]&#xD;
&#xD;
&#xD;
&#xD;
&amp;amp;[Wolfram Notebook][3]&#xD;
&#xD;
&#xD;
  [1]: https://www.wolfram.com/biosciences/&#xD;
  [2]: https://community.wolfram.com//c/portal/getImageAttachment?filename=Poster.png&amp;amp;userId=20103&#xD;
  [3]: https://www.wolframcloud.com/obj/93eb3e71-f5fe-46eb-a5b1-a1243a7fca0a</description>
    <dc:creator>Dimitar Krastev</dc:creator>
    <dc:date>2025-02-14T19:53:57Z</dc:date>
  </item>
</rdf:RDF>

