いわたんち

いわたんちは概念となりました

M1 ProでJapanese InstructBLIP Alphaを動かすメモ

Apple M1 Pro、メモリ32GBでJapanese InstructBLIP Alphaを動かした際のメモ。

基本的には書いてあるとおりに進めたら動いた。

コードはVSCode上でipynbを使って書いた。

pip

必要なライブラリのインストール。

!pip install scipy PILLOW
!pip install sentencepiece einops
!pip install transformers accelerate bitsandbytes

ここでtransformersより先にsentencepieceを入れないとモデルのダウンロード時に次のエラーが出てきた

processor = BlipImageProcessor.from_pretrained("stabilityai/japanese-instructblip-alpha")

TypeError: 'NoneType' object is not callable

コード

import torch
from transformers import LlamaTokenizer, AutoModelForVision2Seq, BlipImageProcessor
from PIL import Image
import requests

# helper function to format input prompts
def build_prompt(prompt="", sep="\n\n### "):
    sys_msg = "以下は、タスクを説明する指示と、文脈のある入力の組み合わせです。要求を適切に満たす応答を書きなさい。"
    p = sys_msg
    roles = ["指示", "応答"]
    user_query = "与えられた画像について、詳細に述べてください。"
    msgs = [": \n" + user_query, ": "]
    if prompt:
        roles.insert(1, "入力")
        msgs.insert(1, ": \n" + prompt)
    for role, msg in zip(roles, msgs):
        p += sep + role + msg
    return p

ここでエラーが出てきてた。あと、cudaは載ってないので基本的にcpuを使うことになるんだけどもmpsを指定したらサポートしてないって怒られた。

# load model
model = AutoModelForVision2Seq.from_pretrained("stabilityai/japanese-instructblip-alpha", trust_remote_code=True)
processor = BlipImageProcessor.from_pretrained("stabilityai/japanese-instructblip-alpha")
tokenizer = LlamaTokenizer.from_pretrained("novelai/nerdstash-tokenizer-v1", additional_special_tokens=['▁▁'])
device = "cuda" if torch.cuda.is_available() else "cpu"
model.to(device)
# prepare inputs
url = "https://images.unsplash.com/photo-1582538885592-e70a5d7ab3d3?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1770&q=80"
image = Image.open(requests.get(url, stream=True).raw).convert("RGB")
prompt = "" # input empty string for image captioning. You can also input questions as prompts 
prompt = build_prompt(prompt)
inputs = processor(images=image, return_tensors="pt")
text_encoding = tokenizer(prompt, add_special_tokens=False, return_tensors="pt")
text_encoding["qformer_input_ids"] = text_encoding["input_ids"].clone()
text_encoding["qformer_attention_mask"] = text_encoding["attention_mask"].clone()
inputs.update(text_encoding)

推論の実行

# generate
outputs = model.generate(
    **inputs.to(device, dtype=model.dtype),
    num_beams=5,
    max_new_tokens=32,
    min_length=1,
)
generated_text = tokenizer.batch_decode(outputs, skip_special_tokens=True)[0].strip()
print(generated_text)

動いた。動いたが、推論に34分もかかった。ヤバい。

そしてメモリ使用量がヤバい。M1はユニファイドメモリなのでVRAM足りなくなるとスワップするの初めて知った。

娘が2歳になったので振り返る

しばらくブログを書いてなかったが、娘が2歳になったので振り返ってみる

できるようになったこと

言語系

  • いやいや言う
  • ばいばいも言える
  • ありがとうは「あーと」と言ってる
  • 見てみてーとアピールしてくる
  • いってきまーす、ただいまーも言える
  • いたいたい、とんでけー
  • 兄のことは「にーに」といったり、「はずくーん」とちょっと違う感じで言ったりする
  • 歌もちょいちょい歌う
    • 咲いた咲いたとか
  • ミッキーやミニーよりもデイジーが好きな様子

身体系

走ったり歩いたりはバッチリできる。 ジャンプをしようとして数センチは飛べる様子。ジャンプするとジャンプしたって報告してくれる

生活リズム

保育園に行ってるので比較的しっかりしてる。7時半ごろに起きて夜は10時前後に寝る。兄よりも寝るのは遅い。 トイレは自分でいける時もある。基本的にはまだまだおむつ。 保育園から帰ってくると「さんぽしたーい」と言って散歩に行ったりしてる。

好み

ディズニーが好きなのは兄弟揃ってな感じ。いないないばーのパンツの歌が好きで良くU-NEXTで観てる。 うどんやそうめんが好きで、お肉は噛めないとペッとする。

1年間で良かった事

二人の子育てになって、上の子だけの時よりも大変になった。 二人目が生まれるタイミングで転職をしており、フルリモートになった。 フルリモートのおかげで、通勤時間が子育てに当てれてる。

近所付き合いも良好で、隣の家の子が1歳違いなので会うとちょいちょい遊んでる。

所感

息子はそんなにイヤイヤ期はなかったが、娘は2歳になる前からイヤイヤ期が凄い。

JavaなFragmentでJetpack Composeを使う時にsetViewCompositionStrategyの指定

kotlinなら

view.setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)

なんだけども、Javaだと

view.setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed.INSTANCE);

とINSTANCEが必要なのがちょっと罠なので注意

Jetpack Composeでサイズに関係なく左右が角丸になるボタンを作る

f:id:iwata_n:20211018235809p:plain

こんな感じにサイズに関係なく左右が角丸になっているボタンを作る

RoundedCornerShapeパーセント指定できるInterface があるのでそれで100%を指定するだけ

謎にハマったところで以下のようにJetpack Composeのパラメータを IntSize で生成すると CommonPreviewUtils.findComposableMethodNoSuchMethodException が出てRender Errorになる

class PreviewSizeProvider : PreviewParameterProvider<IntSize> {
    override val values: Sequence<IntSize>
        get() = sequenceOf(
            IntSize(100, 150),
            IntSize(150, 100),
            IntSize(150, 150),
        )
}

Jetpack Composeで高さを小さくしたTextFieldを作る

こんな感じにIcon、Text、Iconを表示したTextFieldを用意して高さを標準よりも少し小さくしたい場合の対応方法です。

f:id:iwata_n:20211014231136p:plain

こんな感じでModifier.heightで高さを標準よりも小さくすると

var text by remember { mutableStateOf("") }
TextField(
    modifier = Modifier.height(36.dp).background(Color.White),
    value = text,
    onValueChange = {
        text = it
    }
)

f:id:iwata_n:20211014230947p:plain

のようにテキストを入力できるエリアの高さが縮んでしまい入力がまともにできない状態になる。

そんなときは、BasicTextFieldを使って自前でpaddingを含まないTextFieldを用意してあげる。

fun SearchTextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = TextStyle.Default,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions.Default,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    onTextLayout: (TextLayoutResult) -> Unit = {},
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    cursorBrush: Brush = SolidColor(Color.Black),
) {
    BasicTextField(
        value = value,
        onValueChange = onValueChange,
        modifier = modifier
            .background(
                color = MaterialTheme.colors.surface,
                shape = RoundedCornerShape(6.dp)
            ),
        enabled = enabled,
        readOnly = readOnly,
        textStyle = textStyle.copy(
            color = MaterialTheme.colors.onSurface,
        ),
        keyboardOptions = keyboardOptions,
        keyboardActions = keyboardActions,
        visualTransformation = visualTransformation,
        onTextLayout = onTextLayout,
        interactionSource = interactionSource,
        cursorBrush = cursorBrush,
        singleLine = true,
        decorationBox = { innerTextField ->
            Row(
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Icon(
                    Icons.Filled.Search,
                    contentDescription = "search",
                    tint = MaterialTheme.colors.onSurface,
                )
                Box(Modifier.weight(1f)) {
                    if (value.isEmpty()) {
                        Text(
                            text = "検索",
                            style = LocalTextStyle.current.copy(
                                color = MaterialTheme.colors.onSurface,
                            )
                        )
                    }
                    innerTextField()
                }
                Icon(
                    Icons.Filled.Mic,
                    contentDescription = "mic",
                    tint = MaterialTheme.colors.onSurface,
                )
            }
        }
    )
}

冒頭に上げた画像のようにちゃんと高さが小さくできるようになる。

Android Stuido Arctic FoxでシステムUIの日本語が豆腐になったときにやる設定

f:id:iwata_n:20210721214242p:plain

Android Studio Arctic Foxでなんかフォントが変わったのか日本語が豆腐表示になってたので解決方法。 図の場所のチェックを入れると、指定フォントを使うようになるので日本語対応しているフォントに変更すると、文字化けが解消される。

追記:2021/08/02

.AppleSystemUIFontだと検索欄が豆腐になってしまうので、Not Sans CJK等の日本語対応のフォントに変える必要がありました。