パーセプトロンで手書き数字認識(失敗)

適当にやってみたのですが、うまく学習できません・・・
ちゃんと調べてやるべきか。


画面にマウスなんかで数字を書いて、下の数字ボタンで学習します。上の判定ボタンを押すと、標準出力に判定結果を表示します。
3文字くらいまでなら認識できるようになるんだけど。

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class Perceptron extends JComponent implements ActionListener, MouseMotionListener{
    Image img = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
    Graphics bg = img.getGraphics();
    Point pt;
    final int mesh = 10;
    double[][][] perc = new double[10][mesh][mesh];
    double[] b = new double[10];
    double k = 0.1;//学習係数
    
    public static void main(String[] args){
       JFrame f = new JFrame("パーセプトロン");
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       f.setSize(320, 400);
       //描画領域
       Perceptron pc = new Perceptron();
       pc.addMouseMotionListener(pc);
       pc.clear();
       f.add(pc);
       //数字ボタン
       JPanel p = new JPanel();
       p.setLayout(new GridLayout(2, 5));
       for(int i = 0; i < 10; ++i){
           JButton b = new JButton(i +"");
           p.add(b);
           b.addActionListener(pc);
       }
       f.add(p, BorderLayout.SOUTH);
       //判定ボタン
       JButton b = new JButton("判定");
       b.addActionListener(pc);
       f.add(b, BorderLayout.NORTH);
       //ウィンドウ表示
       f.setVisible(true);
    }    
    
    /** ボタンが押されたときの処理 */
    public void actionPerformed(ActionEvent e) {
        //手書き結果を学習メッシュに合わせる
        BufferedImage bi = new BufferedImage(mesh, mesh, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = (Graphics2D) bi.getGraphics();
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
                RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        g2.drawImage(img, 0, 0, mesh, mesh, this);
        
        if("判定".equals(e.getActionCommand())){
            //判定ボタンの処理
            double mr = 0;
            int ans = 0;
            for(int i = 0; i < 10; ++i){
                double r = 0;
                for(int x = 0; x < mesh; ++x){
                    for(int y = 0; y < mesh; ++y){
                        double d = (255 - bi.getRGB(x, y) & 255) / 255.;
                        r += d * perc[i][x][y];
                    }
                }
                r += b[i];
                System.out.printf("%d:%.2f ", i, r);
                if(mr < r){
                    mr = r;
                    ans = i;
                }
            }
            System.out.println("\n答えは" + ans);
            clear();
            return;
        }
        
        //数字ボタンが押されたときの学習処理
        int idx = Integer.parseInt(e.getActionCommand());
        for(int i = 0; i < 10; ++i){
            double yi = (i == idx) ? 1 : -1;
            double in = 0;
            for(int x = 0; x < mesh; ++x){
                for(int y = 0; y < mesh; ++y){
                    double d = (255 - bi.getRGB(x, y) & 255) / 255.;
                    in += d * perc[i][x][y];
                }
            }
            in = (in + b[i]) * yi;
            System.out.printf("%d:% .2f ", i, in);
            if(in <= 0){
                //再学習
                for(int x = 0; x < mesh; ++x){
                    for(int y = 0; y < mesh; ++y){
                        double d = (255 - bi.getRGB(x, y) & 255) / 255.;
                        perc[i][x][y] += d * k * yi;
                        b[i] += k * yi;
                    }
                }                
            }
        }
        System.out.println();
        clear();
    }

    /** マウスで描画 */
    public void mouseDragged(MouseEvent e) {
        Point old = pt;
        pt = e.getPoint();
        if(old != null){
            bg.setColor(Color.BLACK);
            ((Graphics2D)bg).setStroke(new BasicStroke(25));
            bg.drawLine(old.x, old.y, pt.x, pt.y);
            repaint();
        }
    }

    public void mouseMoved(MouseEvent e) {
        pt = null;
    }
    
    //描画
    @Override
    protected void paintComponent(Graphics g) {
        g.drawImage(img, 0, 0, this);
    }
    
    private void clear(){
        bg.setColor(Color.WHITE);
        bg.fillRect(0, 0, 300, 300);
        repaint();
    }
}