これで仕事終わり?さいっこおおおお

ネコの気持ちになりきってのんびりと自由に技術メモを残していきます

next.js 13.4のblogのapp routerについて要約

以前まではpages routerという仕組みが、app routerという機構となり、さらにstableとなった。

本記事は、next.jsを昔ちょろっと触ったことのある程度の筆者の、メモの役割程度のものなので、より詳しい情報が知りたい人は原文を読んでほしい。

nextjs.org

 

以下本文となります。

 

app routerではnext.jsの4つのprinciples:

 

  • Zero setup. Use the filesystem as an API
  • Only JavaScript. Everything is a function
  • Automatic server rendering and code splitting
  • Data fetching is up to the developer

 

に近づくための機能が提供される。

 

zero config

 

next.jsはページ全体の共通の設定などをpages/_app.jsとpages/_document.jsで設定していた。

_app.jsにはlayout定義やglobalな状態管理のためのコンポーネントを用いたラップなどを行う。RecoilRootなどもここに記述する。

_document.jsにはhtllタグやheadタグなどを記述する。

 

app routerではこの2つの設定ファイルを記述する必要がなくなった。

ではどのように変わったのか。

まず、layoutをfolderごとに定義できるようになった。app/があったとき、app/layout.jsをrootのlayoutとして定義すると、app/page.jsではそのレイアウトが適用される。rootのlayoutではhtmlタグなどを記述し、これは_document.jsの代わりとなる。

また、layoutはnestすることができ、app/dashboard/layout.jsを定義すれば、それはdashboard/以下のcomponent用のlayoutとなる。

 

only JavaScript. Everything is a function

 

今まではgetStaticPropsなどdata fetch用の関数をapp/fetch.jsのような外部ファイルに書き出し、componentの記述と分離していた。fetchしたデータはpropsバケツリレーでcomponentに渡していた。

また、getStaticPropasやgetServerSidePropsを明示的に書くことで、data fetchをどこで実行(例:クライアントかサーバーか)するかをnext.jsがよしなに最適化してくれていた。

しかしそれはnext.jsの都合であり、”just JavaScript”の原則に反している。

そこでapp routerでは、component内でのfetchの記述が可能となっている。これによりバケツリレーも減少し、記述は楽になる。

また、デフォルトでcomponentはReact Server Componentsのため、fetchはserver上で実行される。サーバーサイドでのfetchが主となることに付随するキャッシュ戦略などの変化については他の記事を参照されたい。(自分もそのレベルの解釈ができるレベルではない)

 

Data fetching is up to the developer

 

fetchがcomponent内で記述でき、かつserver上で実行されるため、data fetching is up to the developerの原則にもより近づく。

そもそもこの原則は、開発者がより柔軟にfetchを行えるのがいいよねということなので、どんなcomponentでもfetchができるこの機能はよりイケてるよねってことを言いたいんだと思う。(ここは自分でも理解があやふやなので主観です)

例えばreact-tweetのようなサードパーティーのcomponentを用いるときでも、server上でのfetchが保証される。

 

Automatic server rendering and code splitting

 

next.jsが出た当初、renderingやcode splittingの最適化はwebpackなどさまざまなエコシステテムを用いてプロが職人技を披露するといったことが一般的だった。そういった職人技のコストを減らすため、最適化をよしなに行ってくれるいくつかの機能を提供しており、route-basedなcode splittingはその一つである。これは名前の通りpages/ 以下のディレクトリがJS bundleとして分割され、初期表示を高速化する。(単一のドデカjsを読み込まなくて済む)

ただしディレクトリ単位だけでは最適化のプロたちは満足せず、component単位でもcode splittingを行えないかと考えられた。

もちろんnext.jsはそのための機能を提供していたが、next/dynamiからdynamicと呼ばれる関数を呼び出し、その関数に明示的にcomponentを渡してあげる必要があった。

app routerでは、そもそもreact server componetsをデフォルトで利用するためclientのためにjsをbundleすることを考えなくて良い。

またclientのcomponentはwebpack/Turbopackによって自動でsplitされる。

さらにapp routerreact suspense (loading時などに、componentのハンドリングを担当してくれる)を統合しているので、`return isLoggedIn ? <Dashboard /> : <Landing />;`のようにconditionalに、loadingの状態をcode split付きで制御できる。

 

以上

vggのdiscussionが面白かった

初学者な猫

最近cnnを用いたdeep learningについて入門している猫です。

かなり浅くしか読めていませんが、vggの論文のsec 2.3 discussion を読んで、初学者なりに、おおなるほどと思ったことがあったのでメモしておきます。

以下に論文のリンクを貼っておきます。

https://arxiv.org/pdf/1409.1556.pdf

おもしろひ

vggの特徴として、vggが発表されるまで流行っていた構成に比べ、畳み込み層のフィルタを小さく(5×5, 7×7などから3×3に)、そしてネットワーク全体の層を深くしたことがあります

そして、今回猫が面白いなと思った箇所は以下の部分です

It is easy to see that a stack of two 3×3 conv. layers (without spatial pooling in between) has an effective receptive field of 5×5; three such layers have a 7 × 7 effective receptive field.

まあ書いてあることは、3×3のフィルタを2つ積むなら、5×5を1つ積めばよくね?同様に、3×3を3つ積むなら、7×7を1つ積めばよくね?

ということなのですが、ざっくりとした僕の理解では、以下のようなことだと認識しています

参考文献[1]によると、

ここでは、入力サイズを (H, W )、フィルターサイズを (F H, F W )、出力サイズを (OH, OW )、パディングを P 、ストライドを S とします。その場合、出力サイズは 次の式 (7.1) で計算できます。

式が画像ですみません(猫)

計算

今回、パディングは0,ストライドは1,入力画像はW:10, H10としましょう。まあ簡単のためチャネル数も1として、、、

式(7.1)により計算すると、まず3×3の場合は、(OH,OW) = (8,8)で1つ目の出力がなされ、そして2つ目で8×8が入力となり、最終的に(OH,OW) = (6,6)が得られる。

次に5×5の場合、(OH,OW) = (10-5+1,10-5+1) = (6,6)となる

以上の計算より出力サイズは一緒になって良い感じになるよねって話だと思います、サイズの観点からしかみていないので浅い理解ですが

ではなぜ3×3?

論文では、reruを入れられることと、重みについて触れてくれています

So what have we gained by using, for instance, a stack of three 3×3 conv. layers instead of a single 7×7 layer? First, we incorporate three non-linear rectification layers instead of a single one, which makes the decision function more discriminative. Second, we decrease the number of parameters: assuming that both the input and the output of a three-layer 3 × 3 convolution stack has C channels, the stack is parametrised by 3(32 C2)= 27C2 weights; at the same time, a single 7 × 7 conv. layer would require 72 C2 = 49C2 parameters, i.e. 81% more.

1つ目はReluを増やせるので、表現力を増すことができるということだと思います。

2つ目なのですが、畳み込み層の重みは(filter size) × 入力ch数 × 出力ch数であるので、上記のような式となります。

引用を見ると(1 - 49 ÷ 27) *100 %も多いらしいですねこ

なるほどなあ

初学者にはこういったdiscussionはとても勉強になりました

参考文献

[1] ゼロから作るDeep Learning (pythonで学ぶディープラーニングの理論と実装)

comet Ⅱで大文字小文字判定メモ猫

comet Ⅱ すごい

comet Ⅱはモデルアーキテクチャの一つで、一般性を失うことなく簡単化されている。つまり猫でもわかりやすい

今回はcomet Ⅱに対応するアセンブリ言語であるcasl Ⅱを用いて、入力装置から入力された文字が小文字だったら大文字に、大文字だったら小文字に変換し、出力装置に書き込む処理を実現したい(猫が)

かいてみる(猫が)

参考文献のp32のプログラムを参考に記述する

1    C_TRNS  START  
2            IN       CA, CN
3            LD       GR2, CA
4            LAD      GR0, #0060
5            LAD      GR1,  #0020
6            CPA      GR2, GR0
7            JPL      StoL
8            ADDA     GR2, GR1
9            JUMP     WRITE
10   StoL    SUBA     GR2, GR1
11   WRITE   ST       GR2, CA
12           OUT      CA, CN
13           RET
14    CA     DS        256
15    CN     DS         1
16           END

なんとなく理解する

IN, OUT

2行目と12行目で、それぞれ入出力装置からの入出力を行なっている。入力はキーボードなどから、出力はディスプレイなど、の解釈で良さそう?

3,4,5行目

3行目はレジスタ間ロード命令、4,5行目はロードアドレス命令。前者は入力領域CAをレジスタGR2へ転送していて、後者は#0060(文字定数'a'に対する文字コードよりも1だけ小さいデータ)と#0020(小文字データと大文字データの差)をGR0,GR1に格納している。

6~10行目

ここで比較、もし入力文字が#0060よりも小さければ、入力文字は大文字ということであるため、サインフラグがたち、JPLは実行されず、加算処理がなされ、小文字に変換される。

すごい

アセンブリはすごい

少し入門できました

参考文献

コンピュータアーキテクチャ 福本聡, 岩崎一彦 著

pythonでdfs

dfsの勉強がしたいネコ

dfsの勉強がしたいよお 今回は教材として、この方の記事を参考にさせていただきます。

DFS (深さ優先探索) 超入門! 〜 グラフ・アルゴリズムの世界への入口 〜【後編】 - Qiita

解く問題はこれ

A - 深さ優先探索

ほぼ記事通りに、pythonで書いていきます

def dfs_grid(h, w):
    # true:巡回済み
    seen[h][w] = True
    for direction in range(4):
        # new_h,new_w
        nh = h + dx[direction]
        nw = w + dy[direction]
        #進めなかったり巡回済みだったりしたらスルー
        if (nh < 0 or nh >=H or nw < 0 or nw >=W):
            continue
        if field[nh][nw] == '#':
            continue
        if seen[nh][nw]:
            continue
        dfs_grid(nh, nw)



H,W=map(int, input().split())
field=[list(list(input())) for i in range(H)]

# 右、上、左、下
dx = [1, 0, -1, 0]
dy = [0, 1, 0, -1]

seen = [[False for i in range(W)] for j in range(H)]

for h in range(H):
    for w in range(W):
        if field[h][w] == 's':
            sh, sw = h, w
        if field[h][w] == 'g':
            gh, gw = h, w


dfs_grid(sh,sw)

if(seen[gh][gw]):
    print('Yes')
else:
    print('No')

記事が分かり易すぎてすぐにdfsを実装できました、提出するぞ ......

reが出てしまいます

んーーー、reということはindexか、それとももっと何か他のことか、、 とネコのように悩んでいたら、神記事を見つけましたので、参考にさせていただきました

Python 競技プログラミング高速化tips (PythonでAtcoderをやる際に個人的に気を付けてること)

Pythonでは再帰限界が1000回まで決められているので、再帰を使う際はこの限界を上げてあげる必要があります。

だそうです。なるほど

以下のコードを記述すると、reが消えました!ネコ

pythonではあまり再帰は使わない方が良いかもしれません、、

import sys
sys.setrecursionlimit(4100000)

参考文献

DFS (深さ優先探索) 超入門! 〜 グラフ・アルゴリズムの世界への入口 〜【後編】 - Qiita (drken - Qiita)

Python 競技プログラミング高速化tips (PythonでAtcoderをやる際に個人的に気を付けてること) (https://juppy.hatenablog.com/about)

scikit-learnでprecision,recall,f値 [ネコ]

import

import numpy as np
import os

やっていく

mnistを使います

まずはmnistをfetch

from sklearn.datasets import fetch_mldata

mnist = fetch_mldata('MNIST original')
mnist.data.shape
# (70000, 784)

特徴量は28×28で784

70000個インスタンスがあるぽい、70000万匹のネコ.......

mnist.target.shape
# (70000,)

訓練データとテストデータを分けます

60000個が訓練データに、、、60000のネコ

X, y = mnist["data"], mnist["target"]
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]

訓練データをシャッフルします。交差検証の時に検証されない数字があると困るからです。

np.random.seed(42)
shuffle_idx = np.random.permutation(60000)
X_train, y_train = X_train[shuffle_idx], y_train[shuffle_idx]

今回は簡単のため5を判定してみます、これならネコでもわかる!!

5のデータだけtrueに、それ以外はfalseに

この書き方はスッキリしてて良いですね!! スッキリしたねこ,,,,,,,,

y_train_5 = (y_train == 5)
y_test_5 = (y_test == 5)

sgdの分類機を試します、学習させましょう

sgdについては 確率的勾配降下法とは何か、をPythonで動かして解説する - Qiita こちらの記事がわかりやすかったです!天才だ、、

from sklearn.linear_model import SGDClassifier

sgd_clf = SGDClassifier(max_iter=5, tol=-np.infty, random_state=42)
sgd_clf.fit(X_train, y_train_5)

交差検証をします、今回は3フォールドのK分割交差検証でモデルを評価します。この時、cross_val_predict()を使用すると精度ではなく予測結果そのものを返してくれます。

from sklearn.model_selection import cross_val_predict

y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
y_train_pred         # array([False, False, False, ..., False, False, False])

precision, recall, f値を求めましょう!!!終わった、、これでアイス食べれる、、、、

from sklearn.metrics import precision_score, recall_score, f1_score

print('precision:', precision_score(y_train_5, y_train_pred))
print('recall:', recall_score(y_train_5, y_train_pred))
print('f1:', f1_score(y_train_5, y_train_pred))

# precision: 0.7687135020350381
# recall: 0.801328168234643
# f1: 0.7846820809248555

参考文献: scikit-learnとTensorFlowによる実践機械学習 (オライリー・ジャパン, Aurelien geron 著, 下田倫大 監訳, 長尾高弘 訳)