2023年4月28日金曜日

ChatGPTから見た、GPT-4の性能向上と今後の応用

 

どうも。ひっくです。

前回記事を作成した際、ChatGPTを触ってみた感想を書きました。

執筆当時、私は性能の向上にはまだ時間がかかると思っていました。

ところが2023年3月14日(米国時間)にOpenAIからGPT-4が発表され、

その後のSNS上での使用例などを見ると、認識を改めざるを得ないと考えるようになりました。

エンジニアだけでなく、今後多くの職業で生成系AIの活用が必須になると思います。

というわけで、今回もChatGPTについて取り上げます。

GPT-4とGPT-3.5の違い


GPT3.5との大きな違いは以下の3点になるかと思われます。

  • 性能が向上し、専門的な問題も回答できるようになった

      アメリカの司法試験で上位10%の成績を取得(GPT-3.5では下位10%)
  • 長い文章の入出力が可能になった

      最大32000トークン=日本語換算約30000文字(GPT-3.5では4096トークン=日本語換算約3700文字)
  • 画像入力が可能になった

      現時点では研究中のため一部のみ公開。今後公開見込みだが、精度は高そう

 

利用用途


言語を介する作業全般において、様々な応用が可能です。

新事業創出のためのブレーンストーミングや、要件定義から評価まで手助けとなるでしょう。

プロトタイプの作成でも大いに力を発揮します。現在提供されていませんが、画像入力機能が提供されたら

画面イメージから画面そのものを生成することも容易になることが想像できます。

 

また、分からないことがあると調査のためWeb検索することが多いですが、

今後はChatGPTにまず聞いてみることが多くなると思われます。

ファクトチェックが大切であることに変わりはありませんが、

プロンプト(※)に「回答の根拠となったURLがあれば教えて」と含めれば、自分で検索しなおす手間も短くすることができます。

※プロンプト: ユーザーからChatGPTに与えられる入力テキストのこと

 

GPT-4を利用したい場合


現時点では有料版の「ChatGPT Plus」か「API経由」での利用が可能です。

無料で試してみたい場合は、BingAIに「GPT-4」が採用されているのでそちらを利用しましょう。

 

プロンプトエンジニアリングについて


ChatGPTからユーザーが期待する回答を得るためには、プロンプトが重要です。

そのため、プロンプトエンジニアリング(Prompt Engineering)が注目されています。

Prompt Engineering Guide(※) の日本語版に一度目を通しておくことをお勧めします。

※AI研究の海外コミュニティDAIR.AIによって作成されたサイト

 

トークン数の限界について知る


「GPT-4とGPT-3.5の違い」でも触れましたが、一度に入出力が可能なトークン数には限界があります。

ChatGPTと会話をしていると、少し前に話した内容を忘れているように感じることがあるかと思います。

これは、ユーザーとChatGPT間の過去のやり取りをトークン数の限界範囲までで再送信しているためです。

 

トークン数は、OpenAIが提供している以下サイトを利用することで計測可能です。

自分が書いた内容が何トークンになるか知りたい方は利用してみてください。

https://platform.openai.com/tokenizer

 

変数を定義して利用する


トークン数限界を超える会話が行われている場合でも、ある特定の情報は覚えておいて欲しい場合に

変数を定義して情報を覚えてもらう、という方法があります。

 

以下に変数を定義しない場合と、定義した場合の会話例を用意しました。

  • 変数を定義しない場合
  • ~ 長いやりとり~

 

  • 変数を定義した場合
  • ~ 長いやりとり~

 

変数を定義した場合、与えた情報を回答してくれていることが確認できます。

 

まとめ


まだまだ取り上げたい内容はありますが、今回はここまでにします。

今回取り上げた内容もほんの一部でしかないほど、生成系AIを取り巻く環境は相当なスピードで

進んでいます。特にGPT-4が発表された2023年3月14日以降は、ますます進化が加速していると感じます。

 

私自身もChatGPTと会話をする中で、技術的な内容について深く掘り下げられるかどうかは、

自分が持つ技術的な知識量に大きく左右されることを痛感しています。

ChatGPTからの回答に知らない内容が含まれていた場合は、ファクトチェックを行った上で、

正しい情報であれば積極的に吸収するようにしています。

生成系AIに関する最新情報を取得・理解し、同時に自分自身の能力向上を目指していくことが、今後も重要でしょう。

 

今回はこのへんで。ではまた!

2023年4月14日金曜日

PhotoshopのPhotomergeコマンドでパノラマ画像を作成してみた!

新年度が始まり、会社で懇親会を開催しました。 
その模様を当社のYouTubeチャンネルで公開しています。


今回はいつも使用しているDJI Pocket2ではなく、スマホで撮影しました。このところ、スマホではもっぱらショート動画を撮影していたため、横で撮影するのをすっかり忘れていました💦

動画は何とか横で作成したものの、困ったのはサムネイルです。
いつもは動画から書き出したフレームを使用していますが、横のサムネイルを作成するには縦画像を何枚も並べなければなりません。
調べてみると、Photoshopに複数の画像を1つの画像に合成する機能があるようなので、使ってみました。


Photoshopの「Photomerge」コマンド


Photoshopの「Photomerge」コマンドにより、複数の画像を1つの画像に結合することができます。
使い方は簡単で、ファイルー自動処理ーPhotomergeでダイアログを開き、画像ファイルを指定して、「OK」を押すだけです。

今回指定したファイルは、

の6つで、これらを合成すると下の画像が作成されました。この画像をトリミングしてサムネイルを作成しました。

Adobeのサイトを見ると、「各画像の約40%の領域重ねる」とあり、重なりが多くても少なくてもダメなようで、実際、満足いく合成画像を得るまで、何度か画像を変更して試しました。それでも自動で、ここまでの画像を作成してくれるのですから、助かります。


またいつか、どこかで。

2023年4月7日金曜日

archiveEvery="Day"でローテート!ーNLogでログを出力する③

 

こんにちは、せんです。

NLogを使ったログ出力まとめの3回目です。

第1回:インストールから出力まで

第2回:出力フォーマットのカスタマイズ



アーカイブを残すには



ログを出力するときに合わせて考えるのが、アーカイブとローテートです。

前回までの内容で、App.configのターゲット要素は以下のようになっています。
<target name="logFile"
	xsi:type="File"
	encoding="UTF-8"
	fileName="logs/${processname}.log"
	layout="${date} ${level:uppercase=true:padding=-5} -${message} ${exception:format=tostring}" />

この状態でプログラムを数回実行すると、


と、こんな感じで内容が追記されていきます。

ログ出力の日時が書かかれているとはいえ、延々と一つのファイルに書き込まれるのでは、確認が大変ですよね。

というわけで今回は

①区切りのいいところでログファイルを分ける。
②古いログファイルを保存する。
③一定のアーカイブファイルがたまったら、それを削除する。

の3つの作業を行うことで、ログファイルを管理していきたいと思います。



① 区切りのいいところでログファイルを分ける

サイズか日時を設定して、ログを「ローテート」します。
archiveEveryや、archiveAboveSizeというプロパティを使用します。


②古いログファイルを保存する

ローテート後の古いログファイルは、ファイル名を変更しアーカイブフォルダに移動させるなどして保存することができます。
使用するプロパティはarchiveFileName、archiveNumbering、archiveDateFormatです。


③一定のアーカイブファイルがたまったら、それを削除する。

ファイルの保存数、もしくはファイルの保存日数を指定することで、それを超過した場合はファイルが自動で削除されます。
maxArchiveFiles、maxArchiveDaysプロパティを使用します。



ターゲットプロパティまとめ



NLog公式の説明から、ローテートとアーカイブに関するターゲットプロパティをまとめます。

archiveEvery:指定した時間が経過するたびにログファイルを自動アーカイブするかどうか。
       年月日時分のほか、毎週〇曜日という指定ができる。
archiveAboveSize:ログファイルが自動的にアーカイブされるサイズをバイト単位で取得、設定。
         archiveNumbering="Date"との併用は不可。
archiveOldFileOnStartup:起動時に古いログファイルをアーカイブするかどうか。
archiveFileName:アーカイブに使用するファイルの名前を取得、設定。
         方法ごとに一連の数字に置き換えられるプレースホルダ{#####}を含められる。
archiveDateFormat:ファイルアーカイブに使用する日付形式を指定。
          archiveNumbering="Date"または”DateAndSequence”の場合にのみ機能する。
archiveNumbering:ファイルアーカイブに番号を付ける方法。
          archiveNumberingMode
           ・Sequence:シーケンススタイル。最新のアーカイブに最大値。
           ・Rolling:ローリングスタイル。最新は常に#0、#1、…、#Nと続く。
           ・Date:日付スタイル。前回の日時を記載する。
           ・DateAndSequence:日付とシーケンススタイル。
maxArchiveFiles:保持するアーカイブファイルの最大数。
maxArchiveDays:保持するアーカイブファイルの最大日数。



組み合わせて使ってみましょう!



まずはこんな組み合わせで実行します。

 archiveEvery="Minute"
 archiveFileName="logs/archives/${processname}_{#}.log"
 archiveNumbering="Date"
 archiveDateFormat="yyyyMMddHHmmss"
 maxArchiveFiles="3"

ついでにプログラムも変更します。

using System;
using NLog;

namespace UseNLogSample
{
    public class Program
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();

        static void Main(string[] args)
        {
            var timer = new System.Threading.Timer(x => GivenMilletDumplings(), null, 1000, 10000);
            Console.ReadKey();
        }

        private static void GivenMilletDumplings()
{ var companions = new string[] { "犬", "猿", "雉" }; foreach (var companion in companions) { logger.Info($"{companion}は桃太郎からきびだんごをもらいました。"); } } } }

プログラムを実行してlogsフォルダを確認します。
archivesフォルダが生成され、その中にアーカイブファイルが三件追加されます。







分単位でローテートしますが、もっとも古いファイルが削除されているので、フォルダ内のファイル数は三件のままです。




次に、内容を少し変えてみます。

 archiveAboveSize="2000"
 archiveFileName="logs/archives/${processname}_{#}.log"
 archiveNumbering="Sequence"
 maxArchiveFiles="5"

archivesフォルダを確認すると、アーカイブファイルには0から始まるシーケンシャルな番号が振られています。



少し後にもう一度覗いてみると、これまた古いファイルが自動削除されました。
maxArchiveFilesの変更が反映されていることも確認できます。




それでは次はこんな感じで。

 archiveAboveSize="2000"
 archiveFileName="logs/archives/${processname}_{#####}.log"
 archiveNumbering="Rolling"
 maxArchiveFiles="10"

アーカイブファイルに割り振られた番号は、指定の通り五桁になっています。



しばらくしてから覗くと、新しいファイルに置き換わっていますが、ファイル名は同じです。





ここからが本題



 archiveEvery="Day"
 archiveFileName="logs/archives/${processname}_{#}.log"
 archiveNumbering="Date"
 archiveDateFormat="yyyyMMdd"
 maxArchiveFiles="10"

上の設定でプログラムを実行します。
(※メモ:archiveDateFormatの値はarchiveNumbering="Date"に対応するデフォルト値と同じなので、ここではarchiveDateFormatプロパティはなくてもよい。)
次の日にもう一度実行すると、前日のファイルがアーカイブフォルダに移されました!!!


うれしいけど...
あれ、前にやったときはarchiveEvery="Day"だとarchiveフォルダすら作られなかったんだけど、なにか設定が違ったかしら???と思い、調べてみたところ、fileNameを固定の値にしないとアーカイブできないという記事を拝見しました。
(参考記事):https://qiita.com/mak_in/items/b64899b27b5fcf472daa

たしかに、前作った設定ファイルは
fileName="logs/NLogSample_${date:format=yyyyMMdd}.log"
という名前にしている...

でもarchiveEvery="Minute"にすると、ローテートできたんですよね...
まだよくわからない...


さらに調べているとこんな記事も。
最初からログファイル名に日付があれば、archiveEvery="Day"もarchiveFileName="○○"もいらないんじゃない?ということが読み取れます。
ファイル名に日付を指定していれば、別日に実行した時点で別のファイルに書き込まざるを得ないからです。

というわけで、以下の設定で実行します。

<target name="logFile"
xsi:type="File"
encoding="UTF-8"
fileName="logs/${processname}_${date:format=yyyyMMddHHmm}.log"
layout="${date} ${level:uppercase=true:padding=-5} -${message} ${exception:format=tostring}"
maxArchiveFiles="5"/>

※時間の都合上、分まで指定しています。

logsフォルダにmaxArchiveFilesの値+1のファイルが保存されます。



わあ、やっぱりできるんだ...
この辺はケースバイケースですが、どちらも頭に置いておきたいです。



まとめ


ということで、全3回でNLogについてまとめてまいりました。
これまでarchiveEvery="Day"でローテートできたことがなかったので、
日付ローテートすることが裏テーマだったのですが、
なんとかひと段落できてよかったです。