ラベル Lambda の投稿を表示しています。 すべての投稿を表示
ラベル Lambda の投稿を表示しています。 すべての投稿を表示

2020年6月19日金曜日

植物に関する自由記述のJSON化とJavaラムダ式とストリーム(B)

前報(A)の続編です。

(2020-6-21, [検索例(その3)]を追加しました。)

今回の進展
 約3,000行の自然言語による自由形式記述(参考文献[1]にある、植物の一行記述)から、その内容を反映するJSONテキストを自動生成しています。原文に対して係り受け解析を行い(CaboChaにより)、それに基づいてJSONを生成します。係り受け解析結果とJSON生成結果の妥当性検査と、それにもとづいた原文の一部変更という作業を続けてきましたが、このほど終了しました。
 まだまだの状態(JSON自動生成のバージョンはVersion 0.5)ですが、一通りできましたので、以下のとおり、再度いくつかの検索を行ってみました。

自動生成JSONテキストに基づく植物の検索例
 最初の例は、「葉が"倒披針"を含み、花が"白"または"紫"を含む植物」です。検索する主要部は下図のように、Javaの1ステートメントですみます。図中で、jsonStream1は、自動生成したJSONファイルをストリーム化したものです。メソッドbQやpPは小生作成のものです。妥当な検索結果が得られているはずです。

 
 次の例は、「果実のタイプ(type)」を列挙するというものです。上記のその(1)では、.filterと.forEachを使いましたが、ここでは、.mapと.collectを使っている点が違います。概ね妥当(係り受け解析結果の解釈に一部少しの不具合がありますが)な結果のようです。すなわち、このデジタル植物写真集に現れる果実のタイプを概ね列挙しているはずです。


 最後の例は、植物の区分(カテゴリ)毎に"葉"の特徴の記述を集約したものです。多少、処理は複雑にはなりますが、JavaのStreamを処理する強力なgroupingByメソッドのおかげで、見通しのよいコードが書けます。



今後は...
 以上のとおり、植物の葉、花、果実に関するいろいろな検索が少し楽にできるようになったと思います。一方、現状では「穂」や「樹皮」や「茎や根」に関しては、まだJSON生成の対象としていません。今後検討したいと思います。

参考資料
[1] 渡辺 坦:植物の名前を探しやすいデジタル植物写真集
http://plantidentifier.ec-net.jp

2020年6月14日日曜日

植物に関する自由記述のJSON化とJavaラムダ式とストリーム(A)

本記事は、(その3)の続編ですが、少しタイトルを変更しました。

今回の問題設定
 参考資料[1]には、植物を見つけるための1行記述が2,965行(ただしこのうち849行は別名)掲載されています。すなわち、実質約2,100種の植物が掲載されています。そのうちの2例を図1に示します。ここで、例えば、「葉に"楕円"を含み、花に"白"を含む植物」と、そうではなく「果に"楕円"を含み、花に"白"を含む植物」を見つけたいとします。


 単にキーワードとして"楕円"や"白"を含む行を探索するのでは、明らかに妥当な結果が得られません。そのため、自由記述文に形態素解析と係り受け解析を施し、それを基に適切にJSONテキストを生成し、それを使って探索すべきということになりました。

係り受け解析とそれに基づくJSON化は容易か?
 上記のようにして、係り受け解析結果をJSON化することは、実際に行ってみるとそう簡単ではありませんでした。それは、係り受け解析結果が、原文の意味とは異なるケースが少なからずあるからです。その多くの場合、原文に句読点を補う(1文に含まれる複数の単文の区切りを明確にする)こと等で解決しますが、時にはどうしても原文を変更せざるを得ませんでした。その作業は、1行づつ人手で確認しながら進める必要がありました。約3,000行ありますので、1日100行づつ根気強く、確認変更作業を進めています。約1ヶ月かかりますが、まもなく完了します!

 自由に書かれた文の自然言語解析には色々な困難があります。係り受け解析も、簡単なルールだけでは処理仕切れず、機械学習を行っているはずです。人工知能を搭載して、華々しく街へ繰り出した自動運転車もすでに死亡事故を何件か起こしています。学習データの周到な準備は必然ですし、人手による評価修正のフィードバックが必要な状況は続くでしょう。今回のように、3,000件くらいやってみてようやく、自然言語処理の本質が少し見えた来たような気がします。

Javaで自然言語解析する良さがここに現れた
 このように、まだ試行途中なのですが、これまでの作業結果をもとに、上記で設定した問題をやってみました。すなわち、以下の探索を可能にするJavaプログラムを作成しました。
 (1)葉に"楕円"を含み、花に"白"を含む植物
 (2)果に"楕円"を含み、花に"白"を含む植物


 詳しいことは略しますが、図2において、jsonStreamは、生成したJSONテキストをストリーム(stream)化したものです。このストリームの中味は、JSONオブジェクトです。そうなると、ラムダ式を使ったfilterや終端処理としてのforEachの出番です!Javaを使った自然言語処理の良さがここにも現れた気がします。

生成したJSONテキストの概要
 未完成ですが、図3のようなJSONテキストが、係り受け解析結果から自動生成されましたので、ご参考までにその一部をご紹介します。(このJSONテキストは、整形すると全体で約55,000行になります。小生の研究用に生成したものですので、当面、公開はしません。)


参考資料
[1] 渡辺 坦:植物の名前を探しやすいデジタル植物写真集
http://plantidentifier.ec-net.jp

2019年3月30日土曜日

An example of anonymous procedure (lambda expression) in NetLogo (2)

In the last article, I took an example using NetLogo's anonymous procedure (Lambda expressions). This time, as a continuation, I show another simple example. The problem is to find out pairs of right parenthesis and left parenthesis in multiple parentheses structures, as shown in Fig.1. The parentheses structure is given in a text format to the variable paren as shown in (a). The actual structure is as shown in (b). The result of detection of the pairs of left and right parenthesis is illustrated in (c).


This problem can be easily solved using a stack, as is well known. Here, referring to the documents [1] and [2], as shown in Fig. 2, the stack is represented by a list, and the operations of push and pop for it are given by lambda expressions (line 4-line 5). In pop, use the procedure getLast to get (and then to remove) the top element from the list. So far, it is still in preparation.

The actual parentheses check is performed by the foreach in line 5. First, please pay attention to "runresult paren". The variable paren is given the text as described above, but this input form has the ability to create this into a lambda expression for converting text to list. Therefore, runresult is applied. As a result, this part becomes a list. Foreach works on each element of this list, that is, on "(" or on ")". The variable "n" in the lambda expression in line 5 corresponds to one element of the list.

In the procedure "tinit", if the list element is "(", the value obtained by counting up the variable lpc is given to it as a label, and that element is pushed to the stack. On the other hand, if the list element is ")", get the label attached to the "(" at the top of the stack, and then set that label to the ")". This process determines the pair of parentheses. Since push is a lambda expression that does not return a value, it is evaluated by run, whereras,  pop is a lambda expression that returns a value, so it is evaluated by runresult.


Well, "(" and ")" are both turtle agents. In order to display it in an easy-to-understand manner, the shape was defined independently. NetLogo provides a shape editor that allows users to freely define necessary shapes as shown in Fig.3.


References
[1] Alan G. Isaac, https://subversion.american.edu/aisaac/notes/netlogo-intro.xhtml#tasks-vs-procedures
[2] NetLogo Dictionary, https://ccl.northwestern.edu/netlogo/docs/

2019年3月27日水曜日

An example of anonymous procedure (lambda expression) in NetLogo (1)

Let's take advantage of the anonymous procedure in NetLogo programming. This anonymous procedure is called lambda expression in other languages ​​such as Java. An example is shown in Fig.1. Thirty turtles are randomly arranged. Their types are red, pink and white. The problem is to connect the same colored turtles with a line, under the condition that only turtles of the same color in the range of radius 3 are targeted. The result is shown in the figure on the right.



There should be various NetLogo code to achieve this solution. Here, I created a source program like Fig.2.  I added sight as a new property of turtle (Line 1). This is to give turtles the ability to detect the existence of other turtles around them. This sight is given detection capabilities by calling procedure "getSight 3" (line 9). Here, "3" means to detect within the range of radius 3. This sight is quite different from other properties, such as color. The value of color is a constant like "red + 2", but the value of sight is an anonymous procedure (or lambda expression) as shown in line 14.

That is, in the setup procedure below, the value of sight is not determined, but instead a method is given to determine it. The specific value of sight is determined in the go procedure. The command "runresult sight" (line 18) evaluates the lambda expression sight here. The result should be a set of turtles of the same color, within a radius of 3. Then they are connected in a straight line by the command "create-links-with".



Find out all the properties that turtles have. For example, Fig. 3 shows properties for the turtle whose id (who) is 8. As mentioned above, you can confirm that a "procedure (reporter)" is set to sight (at the last row) unlike other properties. In this way, you can handle the procedure as if it were a value, enabling flexible processing in various situations.


2019年1月2日水曜日

Make a mini calendar app for Android, celebrating the New Year

Celebrate the New Year and make a small app! As you can see from the calendar, there are several months with the same day of the week. So, let's make an application that groups months by the day of the week on the 1st day as a key.

[ For Japanese version, please click here.]

grouping months by the day of the week on the 1st day

Although this mini app is not so practical, I will make it with the following five goals:

[1] Make the application logic in Java for Android.
[2] Use lambda expressions, streams, and the new date classes provided by Java 8.
[3] Create a GUI with App Inventor and call Java from there.
[4] Create as a general-purpose framework applicable to other applications.
[5] Customize the ActivityStarter to create a new block.

First, I will talk about [1] and [2]. With the recent Android, we can use Java 8 features. So, I'm going to write this app as concisely as possible using lambda expressions and streams. The logic part is as follows. The essential part is only one assignment statement to a Map object named "mp". The element of this object is a pair of "day of the week" and "a list of months whose first day matches that day of the week".


Next is [3] and [4]. Java programs like the above can be called using App Inventor 's Activity Starter function (block). I will use it, but in order to make it a general-purpose framework, I prepared a template for both the App Inventor side and the Java side. On the Java side, I prepared an input processing part and an output processing part beforehand so that users can complete it by rewriting only the application logic. Also, the App Inventor side has been designed to be applicable to many other applications as shown below. 

A generic App Inventor application that calls Java programs

With regard to the last item [5], I wanted to slightly change the input data and parameters passing to Activity Starter, as a result of considering the versatility as described above. So, I customized ActivityStarter and created new blocks shown below, using AppyBuilder Code Editor. I / O with the Java side was designed to do via a text file. Regarding the input, I provide two ways, passing the path of the input file and passing the text data directly. The boolean parameter "isFile" in the Setup block blow makes this selection possible.


Newly created App Inventor block (customized version of Activity Starter)

The entire App Inventor program created using this new block is as follows.


App Inventor program with newly created block

[Note] About Android and Java 8
Under Android 5.0 (API level 22), it is Java 7 compliant and Java 8 cannot be used. Android 6.0 (API level 23) can use part of lambda expressions etc., but seems to require Android 8.0 (API level 26) or higher in order to use full functions including streams.

2019年1月1日火曜日

新年にちなんでAndroidでカレンダーアプリを作る

みなさま、明けましておめでとうございます。

今年も、拙文ですが、ここに話題を書いて行こうと思っています。新年にちなんで、何か小さなアプリを作ってみたいと思います。カレンダーを眺めていたら、日にちの曜日が同一となっている月が幾つかあります。そこで、月初めの曜日をキーとして、月をグループ化するアプリを作ってみます。
【英語版はこちらにあります】

月初めの曜日が同じ月をグループ化する

実用性には乏しいミニアプリなのですが、以下の5つの「こだわり」を持って作ります。

【1】Android用に、アプリのロジックは、Javaで作る。
【2】Java8のラムダ式とストリーム、改訂日付クラスを用いる。
【3】GUIはApp Inventorで作り、そこからJavaを起動する。
【4】他のアプリにも適用できる汎用的な枠組みとする。
【5】ActivityStarterをカスタマイズして新規ブロックを作る。

まず、【1】と【2】ですが、最近のAndroidでは、Java8の機能が使えることが分かりました。そこで、ラムダ式とストリームを使って、できるだけ簡潔にこのアプリを書いたつもりです。そのロジック部は、以下の通りです。曜日や月の名前は英語ではなく、日本語にすることもできました。本質的な部分は、Mapオブジェクトmpへの代入文1つだけで済んでいます。このmpの要素は、 [曜日, 初日がその曜日である月のリスト]のペアとなります。


次に、【3】と【4】です。上記のようなJavaプログラムは、App InventorのActivity Starter機能(ブロック)を使って、App Inventorから呼び出すことができます。ここでも、それを使うのですが、できるだけ、汎用的な枠組みにするため、App Inventor側とJava側の両方のひな形を用意しました。Java側には、入力処理部と出力処理部を予め備えておき、上図のようなロジックの記述部だけを書き換えるだけで、ほぼ済むようにしました。また、App Inventor側も、下図のような、他の多くのアプリにも適用できるデザインにしました。

Javaプログラムを呼び出す汎用的なApp Inventorアプリ

最後の【5】ですが、上記の汎用性を考えたことにより、Activity Starterに対して、入力データやパラメータの受け渡しを多少変えたくなりました。そこで、それらに関するカスタマイズを行い、新たなブロックを作りました。以下がそれらのブロックです。Java側との入出力は、テキストファイルを介して行うことにしていますが、入力関しては、入力ファイルのパスを渡す場合と、テキストデータを直接渡す場合の2とおりを選べるようにしました。以下にあるSetupブロックの"isFile"でその選択ができます。

新規作成App Inventorブロック(Activity Starterのカスタマイズ版)
この新規ブロックを使って作ったApp Inventorのプログラムの全体は以下のとおりです。

新規作成ブロックを使ったApp Inventorプログラム

【注】AndroidのJava8対応について
Android 5.0(APIレベル22)以下では、Java7対応であり、Java8は使えません。Android 6.0(APIレベル23)ではラムダ式の一部などは使えますが、ストリームも含めたフル機能を使うには、Android 8.0(APIレベル26)以上が必要のようです。

2018年8月29日水曜日

Javaの教科書サポートページに当方の解説資料を掲載していただきました

 Javaプログラミングの書籍は多数あるのですが、そのうち下記の書籍は、Java教科書として広く使われています。神奈川工科大学 情報工学科でも採用されています。現在は第3版ですが、第1版(2000年10月発行)、第2版(2007年月発行)なので、約18年間の実績があります。その間、Javaでは幾つかの大きな改訂がありましたが、それに対応して来られました。

 当方では、この第3版で学ぶに当たっての参考資料(pdf版60ページ)を作成していました。それを、著者の立木秀樹先生(京都大学)により、下記の教科書サポートページに掲載(資料ファイルへのリンク設置)していただきました。皆様にもご活用戴ければ嬉しいです。

https://www.i.h.kyoto-u.ac.jp/users/tsuiki/javaEveryone3/index.html
(このwebページの「リンク」をご覧ください。)


2018年8月5日日曜日

Visualizing Operations on Java Serial/Parallel Streams

Let's examine the operations of streams installed in Java SE8 or later. Again, lambda expression is essential. You can use the CPU performance monitor or peek command to observe the flow of processing (pipeline). However, here we want to observe at a user program level in a more friendly way. There is a good program (StreamTurtle.java) in the examples published at the following URL made by Professors Hideki Tsuiki and Taeko Ariga. 




The above program was created with reference to it.
  • Line 16: A stream composed of integers 1 to 8 is generated.
  • Line 17: Replace each integer of the stream with an object of FPTurtle class which means turtle. Depending on the integer, the (x, y) coordinate and orientation of the turtle are given.
  • Line 21: Each turtle m of the stream draws a polygon with a red color. (The draw method draws a dodecagon with the specified color.) Leave it in the stream.
  • Line 22: Each turtle m of the stream moves slightly to the right and then draws a polygon in green. Leave it in the stream as it is.
  • Line 23: Each turtle m of the stream moves slightly to the right and then draws a polygon with blue color. Leave it in the stream as it is.
  • Line 24: This is a stream end operation. After making each turtle of the stream black, advance forward by 100 steps and stop.



The above figure shows the execution status of this program. Compared to the source list, is something wrong? is something strange? In line 21, all 8 turrets should be red and draw a polygon. After that, in line 22 all turtles draw a green polygon this time. It seems to proceed like that. However, actual execution results are not. As you can see from this execution result, the stream of line 17 begins to run when the aggregation of stream of line 24 starts. Continuously, it flows downward like a pipeline.

Now, let's put the following method call in line 20 of the above list.
          .parallel()
The result of the execution is shown in the figure below. This parallel () is for parallel processing of streams. It was quite different from the previous run. It seems that any four turtles are running at the same time. Exactly, the PC used for this execution has 4 cores. It seems that parallel execution has been done accordingly.






Next, let's run it on another PC with 8 cores. The result is shown below. This time, surely, processing by 8 turtles is always carried out.




The execution time (elapsed time) is also shorter according to the number of used cores as follows. However, since the other programs are running on the PC and the usage of the memory varies, the execution time will fluctuate to some extent each time it is executed.


2018年7月17日火曜日

選択肢はあれど、Javaは使えるようにしたい

Javaプログラミングの演習をとおして、Javaの基礎を身につける。
(本記事の続編は、近々どこかに掲載します。)

Writing with pencil and typing are the basis of this world

ここでは、以下の書籍に特化して、Javaプログラミングを学び、自分の問題解決にJavaを使えるようにすることを目指します。そのためにご参考になりそうなことを書いていきたいと思います。(続編はあるかも)

立木秀樹・有賀妙子「すべての人のためのJavaプログラミング 第3版」共立出版

初版 ー 第2版 ー 第3版

■第3版についての私のコメント

初版(2000年10月発行)、第2版(2007年9月発行)、第3版(2017年10月発行)となっています。私は、大学の情報工学科でこれらの書籍を使って(一時期、別の書籍も教科書として使いましたが)Javaを教え、また、学んで来ました。現在は、学生諸君には教えていませんが、Javaプログラミングは続けています。

この教科書の第一の特徴は、「最初から」タートルグラフィックスを使って、視覚的にプログラムの動作を確認しながら、Javaの基本を学べることです。それは、初版、第2版、第3版でも変わっていません。それまで、C/C++の基礎を教えていた同僚のN先生が、私のJava授業の演習に加わった際に述べられた言葉は印象的でした。「これまでのテキスト主体の演習に比べて、こんなグラフィックスの演習はとても難しいのではないかと思っていたら、学生諸君は意外にも、グイグイとプログラムを書いて、修正して、動かしているのを見て驚きました。これは衝撃的でした!」と。

この教科書は、いわゆる「易しい教科書」に比べて、説明が緻密であり、その結果として文字数がとても多いように見えます。それが、一見、「これはかなり難しい教科書」という印象を与えるかも知れません。しかし、説明文が少なく、文字が大きく、やさしそうに見える教科書は、初心者には逆に理解し難いでしょう。なぜなら、詳しい説明がないのですから、当然そうなります。これに対して、この教科書は、説明に分からないところがあっても、例題のJavaプログラムを動かして、その結果を見ながら、プログラムの構造を見直し、さらに、本文の説明を何度か繰り返して読めば理解が深まってくるように作られています。

第3版になって、変更になった項目で大きなものは、「ラムダ式と関数型インタフェース」の導入と、「これまでのGUIが、SwingからJavaFX」へと変わったことだと思います。前者は、すでに、他の多くのプログラミング言語、例えばPythonやJavaScript等も取り入れていますので、自然な流れと思います。はじめての人は、Javaにおいて、関数をデータとして扱うことには戸惑いを感じると思います。しかし、よく馴染んでくれば、ラムダ式の導入は、従来のオブジェクト指向とうまく融合していることを感じるようになるでしょう。JavaFXへの変更は、より高度なGUI(アニメーション、マルチタッチなどを含む)を持つアプリケーションの作成容易化への要請に応えるもののはずです。なお、本書では、他の多くの書籍にみられるFXML(XMLベース)は扱っていません。これは従来のSwingからの継続性を重視したためかも知れません。

また、後半では、現代のスマートフォンからスーパーコンまでにおいて必須となっている「マルチスレッドと平行処理」に、30ページほどを費やして、丁寧な説明を行っています。その部分にも、上記の「ラムダ式と関数型インタフェース」が出て来ており、ここでも、それらの用途の理解がさらに得られるように思います。