Commit bfd9965c authored by Andor Kyrill Willared's avatar Andor Kyrill Willared

init

parents
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<component name="ProjectDictionaryState">
<dictionary name="Felix" />
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
</project>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Neural-Network-Haskell.iml" filepath="$PROJECT_DIR$/.idea/Neural-Network-Haskell.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
\ No newline at end of file
This diff is collapsed.
import NeuralNetwork
import MNIST
import Util
generate i testSamples = do
if i < 60000 then
vectorToPNG (fst (testSamples!!0)) ("test_"++(show i)++"_" ++ (show (argmax (snd (testSamples!!i)))) ++ ".png")
return generate i+1
else
return
main = do
testSamples <- getTestSamples
generate 0 testSamples
{-|
Module : MNIST
Description : Functions for working with the MNIST dataset
License : MIT
Maintainer : andor.willared@mni.thm.de
Stability : experimental
Provides functions for parsing <http://yann.lecun.com/exdb/mnist MNIST> data, aswell as additional functions for working with PNGSs.
-}
module MNIST (
-- * Parsing
getTrainingSamples,
getTestSamples,
pngToVector,
-- * Rendering
vectorToPNG,
) where
import System.IO
import qualified Data.ByteString as B
import Data.Matrix
import Data.List.Split
import Codec.Picture.Types
import Codec.Picture.RGBA8
import Codec.Picture.Png
-- Parsing
-- | 'getTrainingSamples' is used to parse the raw MNIST training data to a representation usable in Haskell
getTrainingSamples :: FilePath -- ^ Path to "train-images.idx3-ubyte"
-> FilePath -- ^ Path to "train-labels.idx3-ubyte"
-> IO ([(Matrix Float, Matrix Float)]) -- ^ Training data as a list of pairs, where fst represents an image and snd the corresponding label
getTrainingSamples pathImgs pathLabels = do
images <- parseImages pathImgs
labels <- parseLabels pathLabels
return (zip images labels)
-- | 'getTestSamples' is used to parse the raw MNIST test data to a representation usable in Haskel
getTestSamples :: FilePath -- ^ Path to "t10k-images.idx3-ubyte"
-> FilePath -- ^ Path to "t10k-labels.idx3-ubyte"
-> IO ([(Matrix Float, Matrix Float)]) -- ^ Test data as a list of pairs, where fst represents an image and snd the corresponding label
getTestSamples pathImgs pathLabels = do
images <- parseImages pathImgs
labels <- parseLabels pathLabels
return (zip images labels)
-- | 'parseLabels' takes a FilePath and returns a list of matrixes representing the labels
parseLabels :: FilePath -- ^ Path to a MNIST label file
-> IO ([Matrix Float])
parseLabels path = do
labels <- B.readFile path
return (map (fromList 10 1) (map toCategorical10 (map fromIntegral (B.unpack (B.drop 8 labels)))))
-- | 'parseImages' works exactly like 'parseLabels' but returns a representation for images
parseImages :: FilePath
-> IO ([Matrix Float]) -- ^ Path to a MNIST image file
parseImages path = do
images <- B.readFile path
return (map (fmap (/255)) (map (fromList 784 1) (chunksOf 784 (map fromIntegral (B.unpack (B.drop 16 images))))))
-- Png
-- | 'pngToVector' takes a file path and parses it to an equivalent float matrix
pngToVector :: FilePath -- ^ Path to a .png file
-> IO (Matrix Float) -- ^ Float matrix representing the input file
pngToVector path = do
pngData <- B.readFile path
let decodedPng = decodePng pngData
case decodedPng of
Left err -> error (show err)
Right succ -> return fmap (/255.0) (fromList 784 1 (map fromIntegral ([redChannelAt (fromDynamicImage succ) x y | y <- [0..27], x <- [0..27]])))
-- | 'vectorToPng' takes a float matrix and a file path, creates an image representation of the input matrix
--
vectorToPNG :: Matrix Float -- ^ Float matrix to write
-> FilePath -- ^ Path to write the .png to
-> IO()
vectorToPNG vector path = writePng path (generateImage (grayscaleAt vector) 28 28)
-- | 'grayscaleAt' reads a value specified by X and Y from a matrix, returning a PixelRBA8 of the same brightness
grayscaleAt :: Matrix Float -- ^ Matrix to read from
-> Int -- ^ X value
-> Int -- ^ Y value
-> PixelRGBA8
grayscaleAt vector x y = PixelRGBA8 grayscale grayscale grayscale 255
where grayscale = round ((getElem (x+y*28+1) 1 vector)*255)
-- Helper
toCategorical10 :: Int -> [Float]
toCategorical10 label = [if i == label then 1 else 0 | i <- [0..9]]
-- | 'redChannelAt' reads the R value of a Pixel specified by X and Y from a given image
redChannelAt :: Image PixelRGBA8 -- ^ Image to read from
-> Int -- ^ X coordinate of desired pixel
-> Int -- ^ Y coordinate of desired pixel
-> Int
redChannelAt rgba8 x y = redChannel (pixelAt rgba8 x y)
-- | 'redChannel' returns R value of a PixelRGBA8
redChannel :: PixelRGBA8 -- ^ Pixel to read from
-> Int
redChannel (PixelRGBA8 r g b a) = fromIntegral r
This diff is collapsed.
# Neural-Network-Haskell
By Adiel Ahmad, Marco Herzog, Felix Brübach, Jannis Weber, Andor Willared
This is a project for the module "Functional Programming".
## Project
We have implemented a naive neural network in haskell.<br>
You can view the documentation [here](https://git.thm.de/akwl20/neural-network-haskell/blob/master/doc/index.html).<br>
**Our GUI applications only run on Ubuntu!**<br>
### To use our network:
Clone repo, open 'window' under Ubuntu and load 'binary' (pretrained nerual net) into the application if you want to see a trained network.
Or use our network module to use it for your own problem.
{-|
Module : Util
Description : A haskell implementation of a neural network
License : MIT
Maintainer : andor.willared@mni.thm.de
Stability : experimental
Util functions for Machine Learning.
-}
module Util (
argmax,
toCategorical,
shuffle,
reshape
) where
import Data.Matrix
import System.Random
import System.Random.Shuffle (shuffle')
-- | 'argmax' takes a Nx1 matrix and returns the index of the highest value
--
-- __Note__: this function is undefined for NxM matrices
--
--
-- __For example:__
--
-- @> argmax (fromList 4 1 [0,42,1,17]) -- returns 1 @
argmax :: Matrix Float -- ^ matrix
-> Int -- ^ argmax
argmax matrix = snd $ maximum $ zip (toList matrix) [0..(length (toList matrix))]
-- | 'toCategorical' converts a class to a binary class matrix
--
-- __For example:__
--
-- @> toCategorical 1 3 -- returns [0,1,0] @
toCategorical :: Int -- ^ Class
-> Int -- ^ Number of classes
-> Matrix Float -- ^ Binary class matrix
toCategorical _class numOfClasses = fromList numOfClasses 1 [if i == _class then 1 else 0 | i <- [0..numOfClasses-1]]
-- | 'shuffle' randomizes the elements of a list
--
-- __For example:__
--
-- @> shuffle [1,2,3] 42 -> returns [3,2,1] @
shuffle :: [a] -- ^ Unshuffled list
-> Int -- ^ Seed
-> [a] -- ^ Shuffled list
shuffle list seed = shuffle' list (length list) (mkStdGen seed)
-- | 'reshape' transforms a matrix to a given shape
--
-- __For example:__
--
-- @> shuffle [1,2,3] 42 -> returns [3,2,1] @
reshape :: Matrix a -- ^ Matrix to reshape
-> Int -- ^ Rows of reshaped matrix
-> Int -- ^ Columns of reshaped matrix
-> Matrix a -- ^ Reshaped matrix
reshape matrix rows columns = fromList rows columns (toList (transpose matrix))
File added
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>MNIST</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><link rel="stylesheet" type="text/css" href="quick-jump.css" /><script src="haddock-bundle.min.js" async="async" type="text/javascript"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>License</th><td>MIT</td></tr><tr><th>Maintainer</th><td>andor.willared@mni.thm.de</td></tr><tr><th>Stability</th><td>experimental</td></tr><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">MNIST</p></div><div id="table-of-contents"><p class="caption">Contents</p><ul><li><a href="#g:1">Parsing</a></li><li><a href="#g:2">Rendering</a></li></ul></div><div id="description"><p class="caption">Description</p><div class="doc"><p>Provides functions for parsing <a href="http://yann.lecun.com/exdb/mnist">MNIST</a> data, aswell as additional functions for working with PNGSs.</p></div></div><div id="synopsis"><details id="syn"><summary>Synopsis</summary><ul class="details-toggle" data-details-id="syn"><li class="src short"><a href="#v:getTrainingSamples">getTrainingSamples</a> :: FilePath -&gt; FilePath -&gt; IO [(Matrix Float, Matrix Float)]</li><li class="src short"><a href="#v:getTestSamples">getTestSamples</a> :: FilePath -&gt; FilePath -&gt; IO [(Matrix Float, Matrix Float)]</li><li class="src short"><a href="#v:pngToVector">pngToVector</a> :: FilePath -&gt; IO (Matrix Float)</li><li class="src short"><a href="#v:vectorToPNG">vectorToPNG</a> :: Matrix Float -&gt; FilePath -&gt; IO ()</li></ul></details></div><div id="interface"><a href="#g:1" id="g:1"><h1>Parsing</h1></a><div class="top"><p class="src"><a id="v:getTrainingSamples" class="def">getTrainingSamples</a> <a href="#v:getTrainingSamples" class="selflink">#</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">:: FilePath</td><td class="doc"><p>path to &quot;train-images.idx3-ubyte&quot;</p></td></tr><tr><td class="src">-&gt; FilePath</td><td class="doc"><p>path to &quot;train-labels.idx3-ubyte&quot;</p></td></tr><tr><td class="src">-&gt; IO [(Matrix Float, Matrix Float)]</td><td class="doc"><p>Training data as a list of pairs, where fst represents an image and snd the corresponding label</p></td></tr></table></div><div class="doc"><p><code><a href="MNIST.html#v:getTrainingSamples" title="MNIST">getTrainingSamples</a></code> is used to parse the raw MNIST training data to a representation usable in Haskell</p></div></div><div class="top"><p class="src"><a id="v:getTestSamples" class="def">getTestSamples</a> <a href="#v:getTestSamples" class="selflink">#</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">:: FilePath</td><td class="doc"><p>path to &quot;t10k-images.idx3-ubyte&quot;</p></td></tr><tr><td class="src">-&gt; FilePath</td><td class="doc"><p>path to &quot;t10k-labels.idx3-ubyte&quot;</p></td></tr><tr><td class="src">-&gt; IO [(Matrix Float, Matrix Float)]</td><td class="doc"><p>Test data as a list of pairs, where fst represents an image and snd the corresponding label</p></td></tr></table></div><div class="doc"><p><code><a href="MNIST.html#v:getTestSamples" title="MNIST">getTestSamples</a></code> is used to parse the raw MNIST test data to a representation usable in Haskell</p></div></div><div class="top"><p class="src"><a id="v:pngToVector" class="def">pngToVector</a> <a href="#v:pngToVector" class="selflink">#</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">:: FilePath</td><td class="doc"><p>path to a .png file</p></td></tr><tr><td class="src">-&gt; IO (Matrix Float)</td><td class="doc"><p>float matrix representing the input file</p></td></tr></table></div><div class="doc"><p><code><a href="MNIST.html#v:pngToVector" title="MNIST">pngToVector</a></code> takes a file path and parses it to an equivalent float matrix</p></div></div><a href="#g:2" id="g:2"><h1>Rendering</h1></a><div class="top"><p class="src"><a id="v:vectorToPNG" class="def">vectorToPNG</a> <a href="#v:vectorToPNG" class="selflink">#</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">:: Matrix Float</td><td class="doc"><p>float matrix to write</p></td></tr><tr><td class="src">-&gt; FilePath</td><td class="doc"><p>path to write the .png to</p></td></tr><tr><td class="src">-&gt; IO ()</td><td class="doc empty">&nbsp;</td></tr></table></div><div class="doc"><p><code>vectorToPng</code> takes a float matrix and a file path, creates an image representation of the input matrix</p></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.22.0</p></div></body></html>
\ No newline at end of file
This diff is collapsed.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Util</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><link rel="stylesheet" type="text/css" href="quick-jump.css" /><script src="haddock-bundle.min.js" async="async" type="text/javascript"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>License</th><td>MIT</td></tr><tr><th>Maintainer</th><td>andor.willared@mni.thm.de
felix.willared@mni.thm.de
marco.herzog@mni.thm.de
adiel.ahmad@mni.thm.de
jannis.weber@mni.thm.de</td></tr><tr><th>Stability</th><td>experimental</td></tr><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Util</p></div><div id="description"><p class="caption">Description</p><div class="doc"><p>Util functions for Machine Learning.</p></div></div><div id="synopsis"><details id="syn"><summary>Synopsis</summary><ul class="details-toggle" data-details-id="syn"><li class="src short"><a href="#v:argmax">argmax</a> :: Matrix Float -&gt; Int</li><li class="src short"><a href="#v:toCategorical">toCategorical</a> :: Int -&gt; Int -&gt; Matrix Float</li><li class="src short"><a href="#v:shuffle">shuffle</a> :: [a] -&gt; Int -&gt; [a]</li><li class="src short"><a href="#v:reshape">reshape</a> :: Matrix a -&gt; Int -&gt; Int -&gt; Matrix a</li></ul></details></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a id="v:argmax" class="def">argmax</a> <a href="#v:argmax" class="selflink">#</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">:: Matrix Float</td><td class="doc"><p>matrix</p></td></tr><tr><td class="src">-&gt; Int</td><td class="doc"><p>argmax</p></td></tr></table></div><div class="doc"><p><code><a href="Util.html#v:argmax" title="Util">argmax</a></code> takes a Nx1 matrix and returns the index of the highest value
| important: this function is undefined for NxM matrices
<strong>For example:</strong></p><p>@&gt; argmax (fromList 4 1 [0,42,1,17]) -- returns 1</p></div></div><div class="top"><p class="src"><a id="v:toCategorical" class="def">toCategorical</a> <a href="#v:toCategorical" class="selflink">#</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">:: Int</td><td class="doc"><p>class</p></td></tr><tr><td class="src">-&gt; Int</td><td class="doc"><p>number of classes</p></td></tr><tr><td class="src">-&gt; Matrix Float</td><td class="doc"><p>binary class matrix</p></td></tr></table></div><div class="doc"><p><code><a href="Util.html#v:toCategorical" title="Util">toCategorical</a></code> converts a class to a binary class matrix
<strong>For example:</strong></p><p>@&gt; toCategorical 1 3 -- returns [0,1,0]</p></div></div><div class="top"><p class="src"><a id="v:shuffle" class="def">shuffle</a> <a href="#v:shuffle" class="selflink">#</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">:: [a]</td><td class="doc"><p>unshuffled list</p></td></tr><tr><td class="src">-&gt; Int</td><td class="doc"><p>seed</p></td></tr><tr><td class="src">-&gt; [a]</td><td class="doc"><p>shuffled list</p></td></tr></table></div><div class="doc"><p><code><a href="Util.html#v:shuffle" title="Util">shuffle</a></code> shuffles a list
<strong>For example:</strong></p><p>@&gt; shuffle [1,2,3] 42 -&gt; returns [3,2,1]</p></div></div><div class="top"><p class="src"><a id="v:reshape" class="def">reshape</a> <a href="#v:reshape" class="selflink">#</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">:: Matrix a</td><td class="doc"><p>matrix</p></td></tr><tr><td class="src">-&gt; Int</td><td class="doc"><p>rows</p></td></tr><tr><td class="src">-&gt; Int</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src">-&gt; Matrix a</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.22.0</p></div></body></html>
\ No newline at end of file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title> (Index)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><link rel="stylesheet" type="text/css" href="quick-jump.css" /><script src="haddock-bundle.min.js" async="async" type="text/javascript"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption empty">&nbsp;</p></div><div id="content"><div id="index"><p class="caption">Index</p><table><tr><td class="src">argmax</td><td class="module"><a href="Util.html#v:argmax" title="Util">Util</a></td></tr><tr><td class="src">deserialize</td><td class="module"><a href="NeuralNetwork.html#v:deserialize" title="NeuralNetwork">NeuralNetwork</a></td></tr><tr><td class="src">deserializePlain</td><td class="module"><a href="NeuralNetwork.html#v:deserializePlain" title="NeuralNetwork">NeuralNetwork</a></td></tr><tr><td class="src">getTestSamples</td><td class="module"><a href="MNIST.html#v:getTestSamples" title="MNIST">MNIST</a></td></tr><tr><td class="src">getTrainingSamples</td><td class="module"><a href="MNIST.html#v:getTrainingSamples" title="MNIST">MNIST</a></td></tr><tr><td class="src">initNN</td><td class="module"><a href="NeuralNetwork.html#v:initNN" title="NeuralNetwork">NeuralNetwork</a></td></tr><tr><td class="src">multiplyElementwise</td><td class="module"><a href="NeuralNetwork.html#v:multiplyElementwise" title="NeuralNetwork">NeuralNetwork</a></td></tr><tr><td class="src">NeuralNetwork</td><td class="module"><a href="NeuralNetwork.html#t:NeuralNetwork" title="NeuralNetwork">NeuralNetwork</a></td></tr><tr><td class="src">pngToVector</td><td class="module"><a href="MNIST.html#v:pngToVector" title="MNIST">MNIST</a></td></tr><tr><td class="src">predict</td><td class="module"><a href="NeuralNetwork.html#v:predict" title="NeuralNetwork">NeuralNetwork</a></td></tr><tr><td class="src">randomRMatrix</td><td class="module"><a href="NeuralNetwork.html#v:randomRMatrix" title="NeuralNetwork">NeuralNetwork</a></td></tr><tr><td class="src">reshape</td><td class="module"><a href="Util.html#v:reshape" title="Util">Util</a></td></tr><tr><td class="src">serialize</td><td class="module"><a href="NeuralNetwork.html#v:serialize" title="NeuralNetwork">NeuralNetwork</a></td></tr><tr><td class="src">serializePlain</td><td class="module"><a href="NeuralNetwork.html#v:serializePlain" title="NeuralNetwork">NeuralNetwork</a></td></tr><tr><td class="src">shuffle</td><td class="module"><a href="Util.html#v:shuffle" title="Util">Util</a></td></tr><tr><td class="src">sigmoid</td><td class="module"><a href="NeuralNetwork.html#v:sigmoid" title="NeuralNetwork">NeuralNetwork</a></td></tr><tr><td class="src">sigmoid'</td><td class="module"><a href="NeuralNetwork.html#v:sigmoid-39-" title="NeuralNetwork">NeuralNetwork</a></td></tr><tr><td class="src">toCategorical</td><td class="module"><a href="Util.html#v:toCategorical" title="Util">Util</a></td></tr><tr><td class="src">train</td><td class="module"><a href="NeuralNetwork.html#v:train" title="NeuralNetwork">NeuralNetwork</a></td></tr><tr><td class="src">vectorToPNG</td><td class="module"><a href="MNIST.html#v:vectorToPNG" title="MNIST">MNIST</a></td></tr><tr><td class="src">zeroMatrix</td><td class="module"><a href="NeuralNetwork.html#v:zeroMatrix" title="NeuralNetwork">NeuralNetwork</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.22.0</p></div></body></html>
\ No newline at end of file
This diff is collapsed.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title></title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><link rel="stylesheet" type="text/css" href="quick-jump.css" /><script src="haddock-bundle.min.js" async="async" type="text/javascript"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption empty">&nbsp;</p></div><div id="content"><div id="module-list"><p class="caption">Signatures</p></div><div id="module-list"><p class="caption">Modules</p><ul><li><span class="module"><a href="MNIST.html">MNIST</a></span> Functions for working with the MNIST dataset</li><li><span class="module"><a href="NeuralNetwork.html">NeuralNetwork</a></span> A haskell implementation of a neural network</li><li><span class="module"><a href="Util.html">Util</a></span> A haskell implementation of a neural network</li></ul></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.22.0</p></div></body></html>
\ No newline at end of file
{"haddock_version":"2.22.0"}
\ No newline at end of file
This diff is collapsed.
doc/plus.gif

59 Bytes

/* @group Search box layout */
#search {
position: fixed;
top: 3.2em;
bottom: 0;
left: calc(50% - 22em);
width: 44em;
z-index: 1000;
pointer-events: none;
overflow-y: auto;
}
#search.hidden {
display: none;
}
#search-form, #search-results {
box-shadow: 2px 2px 6px rgb(199, 204, 208);
pointer-events: all;
}
#search-form input {
font-size: 1.25em; line-height: 2.3em; height: 2.4em;
display: block;
box-sizing: border-box;
width: 100%;
margin: 0;
padding: 0 0.75em;
border: 0.05em solid rgb(151, 179, 202);
}
#search input:focus {
outline: none;
}
#search p.error {
color: rgb(107, 24, 24);
font-weight: bold;
}
#search-results {
box-sizing: border-box;
border: 0.05em solid #b2d5fb;
background: #e8f3ff;
}
#search-form input + #search-results {
border-top: none;
top: 3em;
max-height: calc(100% - 3em);
}
/* @end */
/* @group search results */
#search-results > ul {
margin: 0;
list-style: none;
}
#search-results > ul > li,
#search-results > p,
#search-results > table {
padding: 0.5em 1em;
margin: 0;
}
#search-results > ul > li {
border-bottom: 1px solid #b2d5fb;
}
#search-results > ul > li > ul {
list-style: none;
}
.search-module h4 {
margin: 0;
}
.search-module > ul {
margin: 0.5em 0 0.5em 2em;
}
.search-module > ul > li > a[href] {
display: block;
color: inherit;
padding: 0.25em 0.5em;
}
.search-module > ul > li > a[href].active-link {
background: #faf9dc;
}
.search-module a[href]:hover {
text-decoration: none;
}
.search-result a a {
pointer-events: none;
}
.search-result ul.subs {
display: inline-block;
margin: 0; padding: 0;
}
.search-result ul.subs li {
display: none;
}
.search-result ul.subs::after {
display: inline-block;
content: "...";
color: rgb(78,98,114);
margin: 0 0.25em;
}
.more-results {
color: rgb(99, 141, 173);
position: relative;
}
.more-results::before {
content: "+";
display: inline-block;
color: #b2d5fb;
font-weight: bold;
font-size: 1.25em; line-height: inherit;
position: absolute;
left: -1em;
}
/* @end */
/* @group Keyboard shortcuts table */
.keyboard-shortcuts {
line-height: 1.6em;
}
.keyboard-shortcuts th {
color: rgb(78,98,114);
}
.keyboard-shortcuts td:first-child,
.keyboard-shortcuts th:first-child {
text-align: right;
padding-right: 0.6em;
}
.key {
display: inline-block;
font-size: 0.9em;
min-width: 0.8em; line-height: 1.2em;
text-align: center;
background: #b2d5fb;
border: 1px solid #74a3d6;
padding: 0 0.2em;
margin: 0 0.1em;
}
/* @end */
File added
import Graphics.UI.Gtk
import qualified Graphics.Rendering.Cairo as C
import Data.IORef
import Control.Monad.State
import Data.Matrix as M
import Codec.Picture.Png
import Codec.Picture.Types
import Data.Text
import NeuralNetwork
import Util
import MNIST
-- constants_begin
matrix_width = 28
matrix_height = 28
tile_size = 24
tile_sizeD = 23.0
least_opacity = 255
window_width = matrix_width * tile_size
window_height = matrix_width * tile_size + 200
-- constants_end
-- check for valid indices in matrix
checkAdjacent :: Int -> Int -> Bool
checkAdjacent x y =
if x >= 1 && x <= matrix_width && y >= 1 && y <= matrix_height
then
True
else
False
-- get nearby on Y-Axis (used for pencil)
getAdjacentY :: Int -> Int -> [(Int,Int)]
getAdjacentY x y = [ (x,ys) | ys <- [(y-1),(y+1)], checkAdjacent x ys]
-- get nearby on X-Axis (used for pencil)
getAdjacentX :: Int -> Int -> [(Int,Int)]
getAdjacentX x y = [ (xs,y) | xs <- [(x-1),(x+1)], checkAdjacent xs y]
-- draw one specific spot in canvas
drawCoordinateSpot :: Double -> Int -> Int -> C.Render ()
drawCoordinateSpot rgb j i =
do
C.rectangle (fromIntegral (tile_size * i + 1)) (fromIntegral(tile_size * j +1)) tile_sizeD tile_sizeD
C.setSourceRGB rgb rgb rgb
C.fill
-- drawMethod for each Value in Matrix
drawCoordinates :: M.Matrix Int -> C.Render ()
drawCoordinates m = do
forM_ [0..(matrix_height-1)] $ \y -> do
forM_ [0..(matrix_width-1)] $ \x -> do
drawCoordinateSpot (fromIntegral ((M.getElem (x+1) (y+1) m))/255) y x
-- EventHandler if window is quit (Gtk)
destroyEventHandler :: IO ()
destroyEventHandler =
do mainQuit
-- updates DrawingArea calls "on paintArea draw $ " (caller for Gtk-Event draw)
updateCanvas :: DrawingArea -> IO Bool
updateCanvas canvas = do
widgetQueueDraw canvas
return False
-- modify value to map on matrix
convert' :: Int -> Int
convert' value = 1 + (value `quot` tile_size)
-- get Pixel of Matrix
getPixel :: Int -> Int -> M.Matrix Int -> Pixel8
getPixel x y matrix = (fromIntegral(M.getElem (x+1) (y+1) matrix))
-- writes an image to path of executeable/binary
imageCreator :: String -> M.Matrix Int -> IO()
imageCreator path matrix = writePng path $ generateImage pixelRenderer matrix_width matrix_height
where pixelRenderer x y = PixelRGBA8 (getPixel x y matrix) (getPixel x y matrix) (getPixel x y matrix) least_opacity
-- converts double value to int
toInt :: Double -> Int
toInt = round
-- Gtk GUIBuilder
main :: IO ()
main =
do
-- initalize Empty Neural Network
net <- (initNN [] 101)
-- create IORef
gnn <- newIORef net
mouseClickState <- newIORef False
drawSpots' <- newIORef (M.zero matrix_width matrix_height)
-- create GTK GUI
initGUI
vBox <- vBoxNew False 1
hBox <- hBoxNew False 2
hBoxBottom <- hBoxNew False 2
vBoxBottom <- vBoxNew False 1
paintArea <- drawingAreaNew
displayField <- labelNew (Just " ")
-- spinButton for naming of traingdata
spinBtn <- spinButtonNewWithRange 0 999999 1
-- entry for naming of traingdata (classes)
entryField <- entryNew
set entryField [ entryPlaceholderText := Just("class") ]
-- entry for path of neural network
loadField <- entryNew
set loadField [ entryPlaceholderText := Just("networkpath") ]
-- Button to load Neural Network
loadBtn <- buttonNew
set loadBtn [ buttonLabel := "Load NN" ]
on loadBtn buttonActivated $ do
nnPath <- entryGetText loadField
loadedNet <- deserialize nnPath
liftIO $ labelSetText displayField "Status: net loaded"
writeIORef gnn loadedNet
return ()
-- Button to save image
saveBtn <- buttonNew
set saveBtn [ buttonLabel := "Save" ]
on saveBtn buttonActivated $ do
classVal <- entryGetText entryField
iterationVal <- spinButtonGetValue spinBtn
localDrawSpots' <- liftIO $ (readIORef drawSpots')
imageCreator (classVal ++"_" ++ (show $ toInt iterationVal) ++ ".png") localDrawSpots'
spinButtonSetValue spinBtn (iterationVal+1)
return ()
-- Button to predict matrix in view
predictBtn <- buttonNew
set predictBtn [ buttonLabel := "Predict" ]
on predictBtn buttonActivated $ do
localNN <- liftIO $ (readIORef gnn)
matrix <- liftIO $ (readIORef drawSpots')
let reshapedMatrix = fmap (/255.0) (fmap fromIntegral (fromList 784 1 (toList (M.transpose matrix))))
let prediction = predict localNN reshapedMatrix -- reshapedMatrix
let res = argmax prediction
liftIO $ labelSetText displayField ("Wert: " ++ (show res))
return ()
-- Button to reset matrix in view
resetBtn <- buttonNew
set resetBtn [ buttonLabel := "Reset" ]
on resetBtn buttonActivated $ do
liftIO $ writeIORef drawSpots' (M.zero matrix_width matrix_height)
liftIO (updateCanvas paintArea)
return ()
-- Gtk window configuration
window <- windowNew
set window [windowDefaultWidth := window_width,
windowDefaultHeight := window_height,
windowWindowPosition := WinPosCenter,
containerChild := vBox,
windowTitle := "Neural Network Demo"]
-- Add GtkEvents to EventListener
widgetAddEvents paintArea [PointerMotionMask, ButtonPressMask, ButtonReleaseMask]
-- handle mouseClickEvent
on paintArea buttonPressEvent $ do
bttnId <- eventButton
liftIO $ writeIORef mouseClickState True
return False
-- handle mouseReleaseEvent
on paintArea buttonReleaseEvent $ do
liftIO $ writeIORef mouseClickState False
return False
-- handle motionNotifyEvent
on paintArea motionNotifyEvent $ do
localMouseClicked <- liftIO $ (readIORef mouseClickState)
if localMouseClicked
then do
(x,y) <- liftIO ( widgetGetPointer paintArea)
localDrawSpots' <- liftIO $ (readIORef drawSpots')
if x > 0 && x < window_width && y > 0 && y < window_width
then do
liftIO $ writeIORef drawSpots' (M.setElem 255 (convert' x, convert' y) localDrawSpots')
-- PENCIL START
forM_ ((getAdjacentX (convert' x) (convert' y)) ++ (getAdjacentY (convert' x) (convert' y))) $ \adj -> do
localDrawSpots' <- liftIO $ (readIORef drawSpots')
if (M.getElem (fst adj) (snd adj) localDrawSpots' >= 255)
then do
return ()
else
liftIO $ writeIORef drawSpots' (M.setElem (255`div`2) (fst adj, snd adj) localDrawSpots')
-- PENCIL END
liftIO (updateCanvas paintArea)
else
return False
else
return False
return False
-- drawCall (called by updateCanvas (internal Gtk EventHandling))
on paintArea draw $ do
localDrawSpots' <- liftIO $ (readIORef drawSpots')
drawCoordinates localDrawSpots'
return ()
on window configureEvent $ do