Commit 862b0389 authored by Felix Brübach's avatar Felix Brübach

added some convinience functions for presentation

parent 844eff28
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
......@@ -13,9 +13,12 @@ module MNIST (
-- * Parsing
getTrainingSamples,
getTestSamples,
getTrainingSamplesWithPaths,
getTestSamplesWithPaths,
pngToVector,
-- * Rendering
vectorToPNG,
render
) where
import System.IO
......@@ -30,22 +33,32 @@ 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' gets mnist training samples if the needed files are in "./mnist/"
getTrainingSamples :: 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
getTrainingSamples = getTrainingSamplesWithPaths "mnist/train-images.idx3-ubyte" "mnist/train-labels.idx1-ubyte"
-- | 'getTrainingSamples' gets mnist test samples if the needed files are in "./mnist/"
getTestSamples :: IO ([(Matrix Float, Matrix Float)]) -- ^ Test data as a list of pairs, where fst represents an image and snd the corresponding label
getTestSamples = getTestSamplesWithPaths "mnist/t10k-images.idx3-ubyte" "mnist/t10k-labels.idx1-ubyte"
-- | 'getTrainingSamplesWithPaths' is used to parse the raw MNIST training data to a representation usable in Haskell
getTrainingSamplesWithPaths :: 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
getTrainingSamplesWithPaths 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
-- | 'getTestSamplesWithPaths' is used to parse the raw MNIST test data to a representation usable in Haskel
getTestSamplesWithPaths :: 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
getTestSamplesWithPaths pathImgs pathLabels = do
images <- parseImages pathImgs
labels <- parseLabels pathLabels
return (zip images labels)
......@@ -76,11 +89,9 @@ pngToVector path = do
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]])))
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()
......@@ -88,30 +99,44 @@ vectorToPNG :: Matrix Float -- ^ Float matrix to write
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
-> PixelRGBA8 -- ^ Grayscale RGBA8
grayscaleAt vector x y = PixelRGBA8 grayscale grayscale grayscale 255
where grayscale = round ((getElem (x+y*28+1) 1 vector)*255)
-- | 'render' renders the input of a samples in the console
render :: Matrix Float -- ^ Matrix to render
-> IO ()
render matrix = do
putStrLn (['\n'] ++ (insert '\n' 28 (map (\x -> if x /= 0 then '.' else ' ') (toList matrix))))
-- 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
-> Int -- ^ Red Channel of the RGBA8 at the desired coordinate
redChannelAt rgba8 x y = redChannel (pixelAt rgba8 x y)
-- | 'redChannel' returns R value of a PixelRGBA8
redChannel :: PixelRGBA8 -- ^ Pixel to read from
-> Int
-> Int -- ^ Red Channel of the RGBA8
redChannel (PixelRGBA8 r g b a) = fromIntegral r
-- | 'insert' inserts a character e in string x at every nth position
insert :: Char -- ^ Character to insert
-> Int -- ^ Frequency
-> [Char] -- ^ List to insert
-> [Char] -- ^ List after insertion
insert _ _ [] = []
insert e n x = ((take n x) ++ [e]) ++ (insert e n (drop n x))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment