Implement basic visualisation for pooling layers.
This commit is contained in:
@@ -68,7 +68,6 @@ InputLayerVisualisation::InputLayerVisualisation(const LayerData &data)
|
||||
void InputLayerVisualisation::render()
|
||||
{
|
||||
const float vertices[] = {
|
||||
// Position, texture coordinates
|
||||
0, 0, 0,
|
||||
0, 0, -targetWidth,
|
||||
0, targetHeight, -targetWidth,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include "LayerVisualisation.hpp"
|
||||
@@ -12,17 +11,18 @@ namespace fmri
|
||||
class MultiImageVisualisation : public LayerVisualisation
|
||||
{
|
||||
public:
|
||||
explicit MultiImageVisualisation(const LayerData&);
|
||||
|
||||
void render() override;
|
||||
|
||||
private:
|
||||
constexpr const static std::array<float, 12> BASE_VERTICES = {
|
||||
0, -1, -1,
|
||||
0, 1, -1,
|
||||
0, 1, 1,
|
||||
0, -1, 1,
|
||||
};
|
||||
|
||||
explicit MultiImageVisualisation(const LayerData&);
|
||||
|
||||
void render() override;
|
||||
|
||||
private:
|
||||
Texture texture;
|
||||
std::unique_ptr<float[]> vertexBuffer;
|
||||
std::unique_ptr<float[]> texCoordBuffer;
|
||||
|
||||
90
src/PoolingLayerAnimation.cpp
Normal file
90
src/PoolingLayerAnimation.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include <glog/logging.h>
|
||||
#include <cmath>
|
||||
#include <caffe/util/math_functions.hpp>
|
||||
#include "PoolingLayerAnimation.hpp"
|
||||
#include "glutils.hpp"
|
||||
#include "Range.hpp"
|
||||
#include "MultiImageVisualisation.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace fmri;
|
||||
|
||||
PoolingLayerAnimation::PoolingLayerAnimation(const LayerData &prevData, const LayerData &curData,
|
||||
const std::vector<float> &prevPositions,
|
||||
const std::vector<float> &curPositions, float xDist) :
|
||||
original(loadTextureForData(prevData)),
|
||||
downSampled(loadTextureForData(curData)),
|
||||
startingPositions(computePositions(prevPositions)),
|
||||
deltas(startingPositions.size())
|
||||
{
|
||||
CHECK_EQ(prevPositions.size(), curPositions.size()) << "Layers should be same size. Caffe error?";
|
||||
|
||||
const float channels = curData.shape()[1];
|
||||
textureCoordinates.reserve(curPositions.size() / 3 * 4);
|
||||
|
||||
const auto downScaling = sqrt(
|
||||
static_cast<float>(curData.shape()[2] * curData.shape()[3]) / (prevData.shape()[2] * prevData.shape()[3]));
|
||||
|
||||
for (auto i : Range(prevPositions.size() / 3)) {
|
||||
const array<float, 8> nodeTexCoords = {
|
||||
1, (i + 1) / channels,
|
||||
1, i / channels,
|
||||
0, i / channels,
|
||||
0, (i + 1) / channels,
|
||||
};
|
||||
|
||||
for (auto coord : nodeTexCoords) {
|
||||
textureCoordinates.push_back(coord);
|
||||
}
|
||||
}
|
||||
|
||||
const auto targetPositions = computePositions(curPositions, downScaling);
|
||||
caffe::caffe_sub(targetPositions.size(), targetPositions.data(), startingPositions.data(), deltas.data());
|
||||
|
||||
for (auto i = 0u; i < deltas.size(); i+=3) {
|
||||
deltas[i] = xDist;
|
||||
}
|
||||
}
|
||||
|
||||
void PoolingLayerAnimation::draw(float timeStep)
|
||||
{
|
||||
vector<float> vertexBuffer(deltas);
|
||||
caffe::caffe_scal(vertexBuffer.size(), timeStep, vertexBuffer.data());
|
||||
caffe::caffe_add(startingPositions.size(), startingPositions.data(), vertexBuffer.data(), vertexBuffer.data());
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
original.bind(GL_TEXTURE_2D);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glVertexPointer(3, GL_FLOAT, 0, vertexBuffer.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, textureCoordinates.data());
|
||||
glDrawArrays(GL_QUADS, 0, vertexBuffer.size() / 3);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
Texture PoolingLayerAnimation::loadTextureForData(const LayerData &data)
|
||||
{
|
||||
CHECK_EQ(data.shape().size(), 4) << "Layer should be image-like";
|
||||
CHECK_EQ(data.shape()[0], 1) << "Only single images supported";
|
||||
|
||||
auto channels = data.shape()[1], width = data.shape()[2], height = data.shape()[3];
|
||||
return loadTexture(data.data(), width, height * channels, channels);
|
||||
}
|
||||
|
||||
vector<float> PoolingLayerAnimation::computePositions(const vector<float> &nodePositions, float scaling)
|
||||
{
|
||||
vector<float> positions;
|
||||
positions.reserve(4 * nodePositions.size());
|
||||
|
||||
for (auto i : Range(nodePositions.size() / 3)) {
|
||||
const float *pos = &nodePositions[3 * i];
|
||||
for (auto j : Range(MultiImageVisualisation::BASE_VERTICES.size())) {
|
||||
positions.push_back(pos[j % 3] + MultiImageVisualisation::BASE_VERTICES[j] * scaling);
|
||||
}
|
||||
}
|
||||
|
||||
return positions;
|
||||
}
|
||||
26
src/PoolingLayerAnimation.hpp
Normal file
26
src/PoolingLayerAnimation.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "Animation.hpp"
|
||||
#include "LayerData.hpp"
|
||||
#include "Texture.hpp"
|
||||
|
||||
namespace fmri
|
||||
{
|
||||
class PoolingLayerAnimation : public Animation
|
||||
{
|
||||
public:
|
||||
PoolingLayerAnimation(const LayerData& prevData, const LayerData& curData, const std::vector<float>& prevPositions, const std::vector<float>& curPositions, float xDist);
|
||||
|
||||
void draw(float timeStep) override;
|
||||
|
||||
private:
|
||||
Texture original;
|
||||
Texture downSampled;
|
||||
std::vector<float> startingPositions;
|
||||
std::vector<float> deltas;
|
||||
std::vector<float> textureCoordinates;
|
||||
|
||||
static Texture loadTextureForData(const LayerData& data);
|
||||
static std::vector<float> computePositions(const std::vector<float> &nodePositions, float scaling = 1);
|
||||
};
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Range.hpp"
|
||||
#include "ActivityAnimation.hpp"
|
||||
#include "InputLayerVisualisation.hpp"
|
||||
#include "PoolingLayerAnimation.hpp"
|
||||
|
||||
using namespace fmri;
|
||||
using namespace std;
|
||||
@@ -188,6 +189,9 @@ Animation * fmri::getActivityAnimation(const fmri::LayerData &prevState, const f
|
||||
case LayerInfo::Type::ReLU:
|
||||
return getReLUAnimation(prevState, curState, prevPositions, curPositions);
|
||||
|
||||
case LayerInfo::Type::Pooling:
|
||||
return new PoolingLayerAnimation(prevState, curState, prevPositions, curPositions, -10);
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user