Post Bank

よわいエンジニアのブログ

TensorFlow LiteのPost-training quantization

TensorFlow Lite公式ページに従って、以下のコードでweightの量子化をしてみた。

import tensorflow as tf

converter = tf.lite.TocoConverter.from_saved_model(saved_model_dir)
converter.post_training_quantize = True
tflite_quantized_model = converter.convert()
open("quantized_model.tflite", "wb").write(tflite_quantized_model)

これを実行すると、weightはfloat32からuint8に変換されるが、計算自体はfloat32のまま浮動小数点数で行われるそうだ。だから、Interpreter#runの入力はfloat32のまま。Post-training quantizationをしたからといって、デモでQuantized modelへの入力をuint8にしているようには出来ない。Full quantization modelを作成するには、Quantization-aware trainingをしないといけないらしい。参考

Androidで非同期処理【Android、Java】

AsyncTaskを使って非同期処理

適当なメソッドからAsyncTaskを直接呼び出して、非同期処理を実行しています。これだとThis AsyncTask class should be static or leaks might occurというWarningが出てしまいました。

public class MainActivity extends AppCompatActivity {

    /* 非同期処理の呼び出し */
    public void asyncTaskSample() {
        new AsyncTask<Integer, Integer, Integer>() {
            @Override
            protected Integer doInBackground(Integer ...params) {
                System.out.println("Hello World!!");
                return 0;
            }
        }.execute(0);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        asyncTaskSample();
    }
}

このエラーの原因を他のサイトから引用します。

  • 非staticな内部クラスは暗黙に親オブジェクト(Activityオブジェクト)への参照を持っている。
  • AsyncTaskが内部的に利用しているスレッドが生きている限りこのオブジェクトがガベージコレクションの対象にならない。

うーん、よくわからない。

この記事にあるように、「非static内部クラスインスタンスが存在する = 外部クラスインスタンスが存在する」という状態のため、非static内部クラスは外部クラスを参照することができるようです。そして参照を持つオブジェクトはガベージコレクションの対象にならないため、非同期処理が終わってもメモリから解放されない。これがメモリリークの原因になってしまうようです。わかったようなわからないような…。

で、原因がわかったところで上のコードをどう直したらいいかと言うと、Warningの通りにAsyncTaskstaticなクラスにする、もしくは、別クラスにすればいいです。以下はstaticなクラスにした例。

public class MainActivity extends AppCompatActivity {

    /* 非同期処理の呼び出し */
    public void asyncTaskSample() {
        MyTask task = new MyTask();
        task.execute(0);
    }

    private static class MyTask extends AsyncTask<Integer, Integer, Integer> {
        @Override
        protected Integer doInBackground(Integer ...params) {
            System.out.println("Hello World!!");
            return 0;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        asyncTaskSample();
    }
}

ただこれでもまだ問題があって、上のコードだとActivityオブジェクトの非staticな変数にアクセスできないです。上のコードでは実装してないけど、ViewとかをMyTaskからいじりたかったりします。そこらへんをどうやってActivityオブジェクトから非同期処理に渡すのが最適かいまいちわかりません。

この記事では、AsyncTaskImageViewを渡すのに、コンストラクタで渡しているのですが、AsyncTaskImageViewへの参照を持たないように、WeakReferenceというのを使っています。参考までに、コードを引用させてもらいます。

class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {  
    private final WeakReference<ImageView> mImageViewReference;  
    int mWidth;  
    int mHeight;  
    String mFilePath;  
  
    public BitmapWorkerTask(ImageView imageView) {  
        mImageViewReference = new WeakReference<ImageView>(imageView);  
        mWidth = imageView.getWidth();  
        mHeight = imageView.getHeight();  
    }  
  
    // バックグラウンドで画像をデコード  
    @Override  
    protected Bitmap doInBackground(String... params) {  
        mFilePath = params[0];  
        return decodeSampledBitmapFromFile(mFilePath, mWidth, mHeight);  
    }  
  
    // ImageView に Bitmap をセット  
    @Override  
    protected void onPostExecute(Bitmap bitmap) {  
        if (mImageViewReference != null && bitmap != null) {  
            final ImageView imageView = mImageViewReference.get();  
            if (imageView != null) {  
                imageView.setImageBitmap(bitmap);  
            }  
        }  
    }  
}

まとめ

結局、方法はいろいろあってどれが最適か正直わかりません。ただ明らかに間違っているコードもネットには散見されるので、注意が必要だなと感じました。(そう言いつつも自分の書いたコードが間違ってるかも...)AsyncTask奥深すぎる...

参考

staticって何?【Java】

この記事がめちゃくちゃわかりやすかった。
staticはクラスの変数、メソッドで、非staticはインスタンスの変数、メソッドということ。

JavaPythonに比べると難しいです。でも勉強になります。Javaって結構古い言語かと思っていたけど、Androidアプリ開発ではまだ結構使われているんですね。今後はKotlinに移行していきそうですけども。

参考

一番かんたんなJava入門

Material-UIでヘッダーを作る【React】

Material-UIを使って、ReactのHeaderコンポーネントを作成する。

準備

以下のコマンドでMaterial-UIをインストールする。

npm install --save @material-ui/core
npm install --save @material-ui/icons

コード

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Drawer from '@material-ui/core/Drawer';
import { Link } from 'gatsby';

const styles = {
  list: {
    width: 250,
  },
  root: {
    flexGrow: 1,
  },
  menuButton: {
    marginLeft: -12,
    marginRight: 20,
  },
};

class Header extends Component {
  state = {
    left: false,
  };

  toggleDrawer = (side, open) => () => {
    this.setState({
      [side]: open,
    });
  };

  render () {
    const { classes } = this.props;

    const sideList = (
      <div className={classes.list}>
        <List>
          <Link to="/">
            <ListItem button>
              <ListItemText primary="Home" />
            </ListItem>
          </Link>
          <Link to="/about">
            <ListItem button>
              <ListItemText primary="About" />
            </ListItem>
          </Link>
        </List>
      </div>
    );

    return (
      <div className={classes.root}>
        <AppBar position="relative" color="inherit">
          <Toolbar>
            <IconButton className={classes.menuButton} color="inherit" aria-label="Menu" onClick={this.toggleDrawer('left', true)}>
              <MenuIcon />
            </IconButton>
            <Drawer open={this.state.left} onClose={this.toggleDrawer('left', false)}>
              <div
                tabIndex={0}
                role="button"
                onClick={this.toggleDrawer('left', false)}
                onKeyDown={this.toggleDrawer('left', false)}
              >
                {sideList}
              </div>
            </Drawer>
            <strong>
              <Link to="/" style={{ boxShadow: 'none', textDecoration: 'none', color: 'inherit', fontFamily: 'Montserrat, sans-serif', }}>Post Bank Extra</Link>
            </strong>
          </Toolbar>
        </AppBar>
      </div>
    );
  }
}

Header.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(Header);

ほぼMaterial-UIのデモコードのコピペ。
stylesは、それぞれのコンポーネントに指定するCSSスタイルを記述している。
sideListで、メニューを開いたときのリンクのリストを作成する。今回はgatsbyLinkコンポーネントを使用しているが、react-router-domとかのLinkでもOK。
メニューを開くかどうかは、stateで管理している。
withStylesは、Material UIのCSS in JSのAPIで、CSSを記述したstylesを引数にとって、classesプロパティを持ったコンポーネントを返す。className={classes.root}などと指定すると、stylesで指定したCSSスタイルを適用することが出来る。

見た目

メニューアイコンをクリックすると、左からメニューが出てくる。

f:id:john_kaz:20181118145403g:plain

まとめ

ReactのCSS適用って色々方法あってどれが最適なのかよくわからない。
上の例みたいにwithStyles使ったり、styleで直接適用するのを混ぜるのは多分間違ってる。

Post Bank Extra

Gatsby.jsで爆速で爆速のブログを作った

Gatsbyは、React用の静的サイトジェネレーターです。
Gatsby + Github pagesでブログを作ってみました。まだまだGatsbyについては理解が整理できてないので、解説は後ほど。
とりあえず、Post Bank Extraもよろしくお願いします。
まだコンテンツが全然ないからか、Gatsbyの実力か、阿部寛のホームページ並みに爆速です。

Post Bank Extra f:id:john_kaz:20181117190129p:plain
追記 2018.12.7
すみません。こちらのブログ一旦メンテナンス中です。

阿部寛のホームページ
f:id:john_kaz:20181117223743p:plain:w300