肉そば屋 喰海の『肉そば』

昼休みに、また天神ビル地下1階にある『肉そば 喰海』に行ってみた。 前回は初来店なのにカツ丼を食べてしまったので、 今度こそ肉そばを食べると決めていたからね。 和そばと特製平麺でかなり悩んだけど、そば屋なんだから和そばを食べるべきと思い、 肉そば大盛り(和そば)を注文。

和そばは極太でコシが強くて、すごく噛み応えがあった。 顎が鍛えられそうだ。 つけ汁はラー油が効いており、 つけ汁のピリ辛さと肉の甘辛さとネギの爽やかさが合わさって、なかなかイケル。 ただ、自分はカツ丼の方が好みかなぁ。

肉そば屋喰海
〒810-0001 福岡県福岡市中央区天神2-12-1 天神ビルB1F飲食街

ベルアメール

ホワイトデーという口実で、仕事帰りに岩田屋本館地下2階にある『ベルアメール』に寄って、 『3種のガナッシュケーキ』を買った。

ホワイトとミルクとビター、 3種のチョコレートの層は見た目にも美味しそうで、実際美味しかった。 チョコレート生地とビターガナッシュがずっしりと濃厚なんだけど、 ミルクガナッシュとホワイトショコラのクリームがふんわりと軽いから、 上手くバランスが取れている。

ついフォークが止まらず、一気に食べてしまった。 1080 円という値段が全然高く感じない満足度。

関連ランキング:チョコレート | 西鉄福岡駅(天神)天神駅天神南駅

『WEB+DB PRESS Vol.97』 を読んだ

『React で作るシングルページアプリケーション入門』で使っている Flux フレームワークは、 Redux ではなく Facebook の flux だった。 flux、以前は dispatcher だけだったのでチェックしていなかったら、 いつの間にか一端の Flux フレームワークになっていたとは。 flux の情報だけでも本特集を読んだ甲斐があった。 あと、サーバーサイドレンダリング(以降 SSR)は最初の表示を高速化するためにやりたいと思っていて、まだやれていない。 SSR するためにはサーバー側に Node のプロセスが必要で、 .NET には一応 React.NET があるけど、 Azure App Services だとプロセス起動できないから使えないんだよな。

『マネージメント入門』では、 マネージメントのノウハウが惜しげもなく紹介されていた。 しかし残念ながら、上が詰まっているため、転職でもしない限り、 自分が本特集で得たノウハウを活用することは無さそうだ。 マネージャーはエンジニアの上位職ではなく違う職種で、 新たに知識やスキルを勉強して身につける必要があると思っている。 エンジニアからマネージャーになって、 そこのところをを怠っている人が多い気がしてならない。

『Emerging Web Technology 研究室【第22回】』は Jupyter Notebook + pandas による Python データ解析の記事だった。 科学技術計算は Python の独壇場だな。 SciPy、特に基盤になっている NumPy が優秀。 .NET だと Math.NET Numerics というライブラリがあって、 演算子オーバーロードしたりして頑張ってはいるが、 Numpy ほど簡潔には書けない。 Deep Learning の実装で身にしみた。 今から Python と同じエコシステムを築くのは困難で、 Ruby から Python のライブラリを使おうとする PyCall のアプローチはとても現実的だ。 負けを認めるみたいでモヤっとしそうなものなのに、その決断が出来るのはスゴイ。

WEB+DB PRESS Vol.97

WEB+DB PRESS Vol.97

肉そば屋 喰海の『かつ丼』

昼休みに、天神ビル地下1階にある『肉そば屋 喰海』に行ってみた。 ここは蕎麦屋なのかな。 グルメ本によってはつけ麺のカテゴリに載ってたりするけど、きっと蕎麦屋だろう。

初めて来たというのに、店名にもなっている肉そばではなく、かつ丼を注文してしまった。 かつ丼も密かに人気を集めているらしいし、実際、客の半数近く注文していた気がする。

かつ丼のトンカツは予想よりも肉厚で食べ応えあった。 卵はちょうど良いふわとろ具合。 つゆは甘めで、卵とご飯によくマッチしていると思う。 値段も 650 円と、コスパは悪くない。 友楽みたいに値段同じでご飯大盛りにできたら嬉しいんだけど、 さすがに無茶な注文だな。

肉そばも気になるので、次回は肉そばを食べることにしよう。

肉そば屋喰海
〒810-0001 福岡県福岡市中央区天神2-12-1 天神ビルB1F飲食街

Xamarin Forms でナビゲーションバーの左側にアイテムを配置する方法メモ

最近、Xamarin Forms で iOS アプリを開発している。 Xamarin Forms は XAML で記述できるので、WPF に慣れている身としては、 Storyboard よりも UI を作成しやすくて良いね。 Grid や StackLayout といったレイアウトが超便利だ。

一方で、「こんなこともできないの?」と思うことも度々ある。 例えば、ナビゲーションバーの左側にアイテムを配置する方法すら提供されていない、とかね。 今回は iOS プロジェクトでカスタムレンダラーを書いて実現できたけど。 こんなやつ。

using System.Collections.Generic;
using System.Linq;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(ContentPage), typeof(XamarinFormsSample.iOS.ContentPageRenderer))]

namespace XamarinFormsSample.iOS
{
    public class ContentPageRenderer : PageRenderer
    {
        public override void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);

            var toolbarItems = ((ContentPage)Element).ToolbarItems.OrderBy(w => w.Priority);
            var navigationItem = NavigationController.TopViewController.NavigationItem;
            var rightItems = new List<UIBarButtonItem>();
            var leftItems =  new List<UIBarButtonItem>();

            foreach (var item in toolbarItems)
            {
                // Priority がマイナスだったらナビゲーションバーの左側に配置する
                if (item.Priority < 0)
                {
                    leftItems.Add(item.ToUIBarButtonItem());
                }
                else
                {
                    rightItems.Add(item.ToUIBarButtonItem());
                }
            }

            navigationItem.SetRightBarButtonItems(rightItems.ToArray(), animated);
            navigationItem.SetLeftBarButtonItems(leftItems.ToArray(), animated);
        }
    }
}

シンプルな UI のアプリなので Xamarin Forms ですんなり実装できると思っていたけど、 結構つまづいている。UIKit 使って実装した方が早かったかも。 今のところ iOS だけが対象だし。

『かぐや様は告らせたい(4)』を読んだ

かぐや様は告らせたい〜天才たちの恋愛頭脳戦〜』の 4 巻がようやく Kindle で発売されたので、 購入して読んだ。

4 巻のお気に入りは藤原書記による特訓回だな。やっぱり。 今回は自分の得意分野だからと侮っていたために、 再び地獄の門を開いてしまうところが、藤原書記らしい。 この回では校歌が出てくるけど、 最後に校歌を使ってオチをつけたのが上手い。 それにしても、白金はこうも欠点が多くてよく会長になれたな。 努力でその場を凌いできたとあるから、 努力で克服していく姿勢が生徒の模範に相応しいと言えなくもないか。

会長の妹・圭が初登場する回も良かった。 圭がどんなキャラクターなのかは、 今回の話だけではまだ掴めなかったけど。 兄を嫌っているフシがあるが、 同属嫌悪的なヤツなのかな。 次回の登場に期待しよう。 この話の見所は妹よりも、黒いかぐや様だな。 もちろん、藤原書記が原因。 主人公(かぐやはヒロインではないみたい)の黒い一面が魅力になっているのが、 このマンガの凄いところだ。

今回も面白かった。既に 5 巻が待ち遠しい。 Kindle 版も紙の本と同時に発売して欲しいけど、 「電子書籍の購入は作家の応援にならない」という記事が記憶に新しいし、 出版業界を変革しないと難しいだろうな。

ニューラルネットワークに対する勾配を実装してみた

C# でゼロから Deep Learning を実装する挑戦の続き。 4 章もようやく終盤で、いよいよ機械学習に入る。 今回はニューラルネットワークに対する勾配を実装してみた。

using System;
using System.Linq;
using MathNet.Numerics.LinearAlgebra;

namespace GradientSimpleNet
{
    class Program
    {
        static void Main(string[] args)
        {
            var net = new SimpleNet();

            // 予測
            var x = Vector<double>.Build.DenseOfArray(new[] { 0.6, 0.9 });
            var p = net.Predict(x);
            Console.WriteLine("予測");
            Console.WriteLine(p);

            // 損失関数の値
            var t = Vector<double>.Build.DenseOfArray(new[] { 0, 0, 1.0 });
            var loss = net.Loss(x, t);
            Console.WriteLine("損失関数の値");
            Console.WriteLine(loss);

            // 勾配
            Func<Matrix<double>, double> f = W => net.Loss(x, t);
            var dW = Gradient.NumericalGradient(f, net.W);
            Console.WriteLine("勾配");
            Console.WriteLine(dW);

            Console.ReadLine();
        }
    }

    static class Functions
    {
        /// <summary>
        /// ソフトマックス
        /// </summary>
        public static Vector<double> Softmax(Vector<double> a)
        {
            var c = a.Max();

            // ベクトルの要素ごとの演算にも Map を使う
            var exp_a = a.Map(x => Math.Exp(x - c));
            var sum_exp_a = exp_a.Sum();
            var y = exp_a.Map(x => x / sum_exp_a);
            return y;
        }

        /// <summary>
        /// 交差エントロピー誤差
        /// </summary>
        public static double CrossEntropyError(Vector<double> y, Vector<double> t)
        {
            var delta = 1e-7;
            return -(y + delta).PointwiseLog().PointwiseMultiply(t).Sum();
        }
    }

    static class Gradient
    {
        /// <summary>
        /// 数値微分
        /// </summary>
        public static Matrix<double> NumericalGradient(Func<Matrix<double>, double> f, Matrix<double> x)
        {
            var h = 1e-4;
            var grad = Matrix<double>.Build.Dense(x.RowCount, x.ColumnCount);

            for (int row = 0; row < x.RowCount; row++)
            {
                for (int column = 0; column < x.ColumnCount; column++)
                {
                    var tmpVal = x[row, column];

                    x[row, column] = tmpVal + h;
                    var fxh1 = f(x);

                    x[row, column] = tmpVal - h;
                    var fxh2 = f(x);

                    grad[row, column] = (fxh1 - fxh2) / (2.0 * h);

                    // 値を元に戻す
                    x[row, column] = tmpVal;
                }
            }

            return grad;
        }
    }

    class SimpleNet
    {
        /// <summary>
        /// 重みパラメーター
        /// </summary>
        public Matrix<double> W { get; }

        public SimpleNet()
        {
            // ゼロから作る Deep Learning と同じ重みパラメーターを指定する
            W = Matrix<double>.Build.DenseOfArray(new double[,]
            {
                { 0.47355232, 0.9977393, 0.84668094 },
                { 0.85557411, 0.03563661, 0.69422093 }
            });
        }

        public Vector<double> Predict(Vector<double> x)
        {
            return x * W;
        }

        public double Loss(Vector<double> x, Vector<double> t)
        {
            var z = Predict(x);
            var y = Functions.Softmax(z);
            var loss = Functions.CrossEntropyError(y, t);
            return loss;
        }
    }
}

実行結果は次の通り。

『ゼロから作る Deep Learning』と同じような傾向になっている。 完全に一致しないのは、自分の実装が間違っているんだろうか。