2017-06-18

【備忘録】Rのplsパッケージの使い方

PLS 回帰, Partial Least Squares Regression(部分的最小二乗回帰)とは、目的変数 Yを予測するために係数を最適化する手法のひとつです。

業務でこの手法を応用したツールを使っているのですが、導き出した結果を検証する環境を探していたところ、R の pls パッケージであれば十分な検証ができそうだということが判りました。そこで、この pls パッケージの使い方を備忘録的にまとめました。

動作環境は次の通りです。

  • OS: Fedora 26 x86_64 (beta)
  • R-core-3.4.0-2.fc26.x86_64
  • rstudio-1.0.143-1.x86_64

ここでは参考サイト [1] に従って、自分で動作を確認して備忘録にすることが目的なので、統計的解釈に深くは立ち入っていないことをご了承下さい。また、あとで得た知見で書き直したり書き足したりすることもあります。

pls パッケージのインストール

R を起動して、以下のコマンドで pls パッケージをインストールします。

> install.packages("pls")
 パッケージを ‘/home/bitwalk/R/x86_64-redhat-linux-gnu-library/3.4’ 中にインストールします 
 (‘lib’ が指定されていないため) 
 --- このセッションで使うために、CRAN のミラーサイトを選んでください --- 
 URL 'https://cran.ism.ac.jp/src/contrib/pls_2.6-0.tar.gz' を試しています 
Content type 'application/x-gzip' length 809111 bytes (790 KB)
==================================================
downloaded 790 KB

* installing *source* package ‘pls’ ...
**  パッケージ ‘pls’ の解凍および MD5 サムの検証に成功しました 
** R
** data
*** moving datasets to lazyload DB
** inst
** preparing package for lazy loading
** help
*** installing help indices
  converting help for package ‘pls’
    finding HTML links ...  完了 
    biplot.mvr                              html  
...
...
** building package indices
** installing vignettes
** testing if installed package can be loaded
* DONE (pls)

 ダウンロードされたパッケージは、以下にあります 
  ‘/tmp/RtmpBE2Z3b/downloaded_packages’ 
> 

最初に、pls パッケージを library でロードしておきます。

> library(pls)
 次のパッケージを付け加えます: ‘pls’ 

 以下のオブジェクトは ‘package:stats’ からマスクされています: 

     loadings 

> 

使用するサンプル

以下のサンプルデータを用いますので、data でロードします。

> data(gasoline)

データの精度を4桁に設定します。

> options(digits = 4)

サンプルデータ gasoline の解析

> ?gasoline
gasoline                  package:pls                  R Documentation

Octane numbers and NIR spectra of gasoline

Description:

     A data set with NIR spectra and octane numbers of 60 gasoline
     samples.  The NIR spectra were measured using diffuse reflectance
     as log(1/R) from 900 nm to 1700 nm in 2 nm intervals, giving 401
     wavelengths.  Many thanks to John H. Kalivas.

Usage:

     gasoline
     
Format:

     A data frame with 60 observations on the following 2 variables.

     ‘octane’ a numeric vector.  The octane number.

     ‘NIR’ a matrix with 401 columns.  The NIR spectrum.

Source:

     Kalivas, John H. (1997) Two Data Sets of Near Infrared Spectra
     _Chemometrics and Intelligent Laboratory Systems_, *37*, 255-259.

サンプルの gasoline データ(オクタン価とガソリンの拡散反射の近赤外線分光データ、NIR スペクトル)を解析します。データは以下のような構造になっています。

> names(gasoline)
[1] "octane" "NIR"   
> gasoline$octane
 [1] 85.30 85.25 88.45 83.40 87.90 85.50 88.90 88.30 88.70 88.45 88.75 88.25
[13] 87.30 88.00 88.70 85.50 88.65 88.75 85.40 88.60 87.00 87.15 87.05 87.25
[25] 86.85 88.65 86.60 86.00 86.10 86.50 86.30 84.40 84.70 84.60 84.50 88.10
[37] 85.25 88.40 88.20 88.40 88.55 88.35 88.20 85.30 88.50 88.25 88.00 88.85
[49] 88.45 88.70 88.10 87.60 88.35 85.10 85.10 84.70 87.20 86.60 89.60 87.10
> gasoline$NIR
      900 nm    902 nm    904 nm    906 nm    908 nm    910 nm    912 nm
1  -0.050193 -0.045903 -0.042187 -0.037177 -0.033348 -0.031207 -0.030036
2  -0.044227 -0.039602 -0.035673 -0.030911 -0.026675 -0.023871 -0.022571
...
...
 [ reached getOption("max.print") -- 58 行を無視しました ] 

gasoline$octane の要素は、波長ごとに NIR スペクトルのリスト(ベクトル)になっています。もう少し詳しく調べてみます。

> dim(gasoline$NIR)
[1]  60 401
> dimnames(gasoline$NIR)
[[1]]
 [1] "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9"  "10" "11" "12" "13" "14" "15" "16"
[17] "17" "18" "19" "20" "21" "22" "23" "24" "25" "26" "27" "28" "29" "30" "31" "32"
[33] "33" "34" "35" "36" "37" "38" "39" "40" "41" "42" "43" "44" "45" "46" "47" "48"
[49] "49" "50" "51" "52" "53" "54" "55" "56" "57" "58" "59" "60"

[[2]]
  [1] "900 nm"  "902 nm"  "904 nm"  "906 nm"  "908 nm"  "910 nm"  "912 nm"  "914 nm" 
  [9] "916 nm"  "918 nm"  "920 nm"  "922 nm"  "924 nm"  "926 nm"  "928 nm"  "930 nm" 
...
...
[393] "1684 nm" "1686 nm" "1688 nm" "1690 nm" "1692 nm" "1694 nm" "1696 nm" "1698 nm"
[401] "1700 nm"

イメージしやすいように、gasoline$octane のデータについて、波長を横軸にとってプロットしてみました。もっとスマートなプロットの仕方があると思いますが、とりあえず、これでお許しください。

> y.values <- gasoline$NIR
> x.label <- colnames(y.values)
> x.value <- as.numeric(substring(x.label, 1, nchar(x.label) - 3))
> plot(x.value, y.values[1,], type = "n", main = "NIR spectra of gasoline samples", xlab = "wavelength", ylab = "log(1/R)")
> for (i in 1:nrow(y.values)) lines(x.value, y.values[i, ], type = "l")

このデータ解析の目的は、

octane = f(NIR) = f(NIRwavelength1, NIRwavelength2, ...)

という関数関係を求めて、スペクトルからオクタン価を予測することなのですが、401 個の変数(NIR スペクトル)、60 組のデータでは、従来の重回帰分析を使おうとしても自由度が全然足りなくて解析できません。しかし、401 個のデータは互いに独立した関係にないので、これら NIR スペクトルの代わりに、主成分分析で主成分に分解し、目的変数と相関のある成分 compn から関数関係を求めます。

octane = g(compwavelength1, compwavelength2, ...)

まず、データをトレーニング用とテスト用の二つに分けます。

> gasTrain <- gasoline[1:50,]
> gasTest <- gasoline[51:60,]

フィッティングはトレーニング用のデータ gasTrain を用いて次のようにします。

> gas1 <- plsr(octane ~ NIR, ncomp = 10, data = gasTrain, validation = "LOO")

このフィッティングでは 10 個の成分で行われ、一個抜き交差検証, leave-one-out (LOO) cross-validated predictions が実施されています。

フィッティングと検証結果は summary で確認できます。

> summary(gas1)
Data:  X dimension: 50 401 
 Y dimension: 50 1
Fit method: kernelpls
Number of components considered: 10

VALIDATION: RMSEP
Cross-validated using 50 leave-one-out segments.
       (Intercept)  1 comps  2 comps  3 comps  4 comps  5 comps  6 comps  7 comps  8 comps  9 comps  10 comps
CV           1.545    1.357   0.2966   0.2524   0.2476   0.2398   0.2319   0.2386   0.2316   0.2449    0.2673
adjCV        1.545    1.356   0.2947   0.2521   0.2478   0.2388   0.2313   0.2377   0.2308   0.2438    0.2657

TRAINING: % variance explained
        1 comps  2 comps  3 comps  4 comps  5 comps  6 comps  7 comps  8 comps  9 comps  10 comps
X         78.17    85.58    93.41    96.06    96.94    97.89    98.38    98.85    99.02     99.19
octane    29.39    96.85    97.89    98.26    98.86    98.96    99.09    99.16    99.28     99.39>

ちなみに、gas1 は以下のような構造になっています。

> names(gas1)
 [1] "coefficients"    "scores"          "loadings"        "loading.weights"
 [5] "Yscores"         "Yloadings"       "projection"      "Xmeans"         
 [9] "Ymeans"          "fitted.values"   "residuals"       "Xvar"           
[13] "Xtotvar"         "fit.time"        "ncomp"           "method"         
[17] "validation"      "call"            "terms"           "model"

実測値と予測値の最小二乗誤差 RMSEP, Root Mean Square Error of Prediction が小さいほどフィッティングが良いと考えることができます。gas1 では成分 (comps) が 10 までの関係を調べてありますので、成分の数とフィッティング (RMSEP) との関係をプロットしてみます。

> plot(RMSEP(gas1), legendpos = "topright")

このプロットによると、octane を表現するのに二成分あればほぼ十分であるということが判ります。二成分のときの RMSEP は 0.2966 です。

成分の数が決まれば、その成分で予測した値と実測値との相関を確認することができます。

> plot(gas1, ncomp = 2, asp = 1, line = TRUE)

次に最初の3つの成分の得点 score の一覧表を作ります。

> plot(gas1, plottype = "scores", comps = 1:3)

この例では、特に目立った傾向が見られません。成分の得点一覧は次のように explvar で表示できます。

> explvar(gas1)
    Comp 1     Comp 2     Comp 3     Comp 4     Comp 5     Comp 6     Comp 7     Comp 8     Comp 9    Comp 10 
78.1707683  7.4122245  7.8241556  2.6577773  0.8768214  0.9466384  0.4921537  0.4723207  0.1688272  0.1693770 
>

成分の負荷量 loading をプロットすることは、成分を解釈するためによく使われます。

> plot(gas1, "loadings", comps = 1:2, legendpos = "topleft", labels = "numbers", xlab = "nm")

解析を始める前にデータをトレーニング用とテスト用の二つに分けましたが、テスト用のデータ gasTest を用いて、二つの成分で予測値を計算するには次のようにします。

> predict(gas1, ncomp = 2, newdata = gasTest)
, , 2 comps

     octane
51 87.94125
52 87.25242
53 88.15832
54 84.96913
55 85.15396
56 84.51415
57 87.56190
58 86.84622
59 89.18925
60 87.09116

> 

テスト用のデータ gasTest は octane の実測値が含まれていますので、各成分数ごとの予測値との RMSEP を算出することができます。

> RMSEP(gas1, newdata = gasTest)
(Intercept)      1 comps      2 comps      3 comps      4 comps      5 comps      6 comps      7 comps      8 comps      9 comps     10 comps  
     1.5369       1.1696       0.2445       0.2341       0.3287       0.2780       0.2703       0.3301       0.3571       0.4090       0.6116  
> 

まとめ

参考サイト [1] の一部を、自分で確認してきましたが、これでおおよその使い方を掴めました。あとは、自分のデータを使って、業務で使っているツールが導き出す結果を検証できるように、もう少しこのパッケージを使い込んでいきたいと考えています。

参考サイト

  1. Introduction to the pls Package

 

ブログランキング・にほんブログ村へ
にほんブログ村

2017-05-26

【備忘録】JavaFXで8種より多いシンボルを LineChart に表示する

R を使ってある事象をチャートで説明したところ、なんと(社内の)担当者が R のスクリプトを理解できないということが判明し、仕方なく JavaFX で同じようなプロットを作ることになりました。R ではスマートに計算できるベクトルの計算が、Java ではうまく行かず冗長になりますが、それでもやってやれないことはないと取り掛かったのですが、思わぬところで行き詰まってしまいました。この作業では珍しくシンボルの数が多いのですが、今までのやり方では8種までしかシンボルの色などを設定できなかったのです。

下記は無事この問題が解決した後のプロット例です。

従来は下記のように CSS ファイルで、.default-color0.chart-... の太字の数字の部分を順番に 0, 1, 2, ... と増やして対応させていましたが、この方法だと 7 までしか使えません。

.default-color0.chart-series-line { ... }
.default-color0.chart-line-symbol { ... }
...
...
...

参考サイト [1] によると、.default-color0.chart-... を使わずに、代わりに .series0.chart-... を使うと良いとのことです。下記のようにして 14 種類の線およびシンボルを無事表示されることができました。

リスト:シンボルが多いときの CSS 設定例 
.chart-series-line {
    -fx-stroke-width: 1px;
    -fx-effect: null;
}

.series0.chart-series-line { -fx-stroke: transparent; }
.series0.chart-line-symbol {
    -fx-background-color: #c0c0c0, #c0c0c0;
    -fx-background-radius: 3px;
    -fx-padding: 3px;
}

.series1.chart-legend-item-symbol {
    -fx-background-color: #ff0000;
    -fx-background-radius: 0;
    -fx-background-insets: 0;
    -fx-shape: "M0,5 L0,7 L12,7 L12,5 Z";
    -fx-scale-shape: false;
}

.series2.chart-series-line {
    -fx-stroke: #ff0000;
    -fx-stroke-width: 1px;
}
.series2.chart-line-symbol {
    -fx-background-color: #ff0000, #ff0000;
    -fx-background-radius: 0px;
    -fx-padding: 0px;
}
.series2.chart-legend-item-symbol {
    -fx-background-color: #ff0000;
    -fx-background-radius: 0;
    -fx-background-insets: 0;
    -fx-shape: "M0,5 L0,7 L12,7 L12,5 Z";
    -fx-scale-shape: false;
}

.series3.chart-series-line { -fx-stroke: transparent; }
.series3.chart-line-symbol {
    -fx-background-color: #008080, #008080;
    -fx-background-radius: 2px;
    -fx-padding: 2px;
}
.series4.chart-series-line { -fx-stroke: transparent; }
.series4.chart-line-symbol {
    -fx-background-color: #008080, #008080;
    -fx-background-radius: 0;
    -fx-background-insets: 0;
    -fx-shape: "M2,0 L5,4 L8,0 L10,0 L10,2 L6,5 L10,8 L10,10 L8,10 L5,6 L2,
        10 L0,10 L0,8 L4,5 L0,2 L0,0 Z";
}

.series5.chart-series-line { -fx-stroke: transparent; }
.series5.chart-line-symbol {
    -fx-background-color: #0040c0, #0040c0;
    -fx-background-radius: 2px;
    -fx-padding: 2px;
}
.series6.chart-series-line { -fx-stroke: transparent; }
.series6.chart-line-symbol {
    -fx-background-color: #0040c0, #0040c0;
    -fx-background-radius: 0;
    -fx-background-insets: 0;
    -fx-shape: "M2,0 L5,4 L8,0 L10,0 L10,2 L6,5 L10,8 L10,10 L8,10 L5,6 L2,
        10 L0,10 L0,8 L4,5 L0,2 L0,0 Z";
}

.series7.chart-series-line { -fx-stroke: transparent; }
.series7.chart-line-symbol {
    -fx-background-color: #0000ff, #0000ff;
    -fx-background-radius: 2px;
    -fx-padding: 2px;
}
.series8.chart-series-line { -fx-stroke: transparent; }
.series8.chart-line-symbol {
    -fx-background-color: #0000ff, #0000ff;
    -fx-background-radius: 0;
    -fx-background-insets: 0;
    -fx-shape: "M2,0 L5,4 L8,0 L10,0 L10,2 L6,5 L10,8 L10,10 L8,10 L5,6 L2,
        10 L0,10 L0,8 L4,5 L0,2 L0,0 Z";
}

.series9.chart-series-line { -fx-stroke: transparent; }
.series9.chart-line-symbol {
    -fx-background-color: #4000c0, #4000c0;
    -fx-background-radius: 2px;
    -fx-padding: 2px;
}
.series10.chart-series-line { -fx-stroke: transparent; }
.series10.chart-line-symbol {
    -fx-background-color: #4000c0, #4000c0;
    -fx-background-radius: 0;
    -fx-background-insets: 0;
    -fx-shape: "M2,0 L5,4 L8,0 L10,0 L10,2 L6,5 L10,8 L10,10 L8,10 L5,6 L2,
        10 L0,10 L0,8 L4,5 L0,2 L0,0 Z";
}

.series11.chart-series-line { -fx-stroke: transparent; }
.series11.chart-line-symbol {
    -fx-background-color: #800080, #800080;
    -fx-background-radius: 2px;
    -fx-padding: 2px;
}
.series12.chart-series-line { -fx-stroke: transparent; }
.series12.chart-line-symbol {
    -fx-background-color: #800080, #800080;
    -fx-background-radius: 0;
    -fx-background-insets: 0;
    -fx-shape: "M2,0 L5,4 L8,0 L10,0 L10,2 L6,5 L10,8 L10,10 L8,10 L5,6 L2,
        10 L0,10 L0,8 L4,5 L0,2 L0,0 Z";
}

.series13.chart-series-line { -fx-stroke: transparent; }
.series13.chart-line-symbol {
    -fx-background-color: #ff0000, #ff0000;
    -fx-background-radius: 4px;
    -fx-padding: 4px;
}

JavaFX に書き直したからと言って、くだんの担当者に理解してもらえるかどうかはあやしいのですが、このことで出来なかったことが出来るようになったので良しとし、備忘録としました。

参考サイト

  1. java - setting more than eight colors for data series in JavaFX ScatterChart - Stack Overflow
  2. bitWalk's: JavaFX: LineChart を使いこなそう (3)

 

ブログランキング・にほんブログ村へ
にほんブログ村

2017-05-06

Fedora 26 アルファ版へアップグレード

Linux ディストリビューションのひとつ、Fedora は、年に二回の頻度で新しいバージョンがリリースされています。スケジュール通りにリリースされれば、5 月の連休中にベータバージョンをインストールできるのですが、リリーススケジュールは遅延するのが常です。次期バージョンの Fedora 26 のベータリリースは、現時点では 2017-05-30 となっています [1]

この連休中にアップグレードを済ませておきたかったので、以下の手順で Fedora 25 からアルファ版の Fedora 26 へアップグレードしました。

  1. dnf update --refresh
  2. dnf install dnf-plugin-system-upgrade
  3. dnf system-upgrade download --releasever=26
  4. dnf system-upgrade reboot

以下が実際の例です。

$ su
パスワード:
# dnf update --refresh
Dropbox Repository                              8.2 kB/s | 2.4 kB     00:00    
google-chrome                                    38 kB/s | 3.8 kB     00:00    
Visual Studio Code                              388 kB/s | 238 kB     00:00    
依存性が解決されました。
================================================================================
 Package      アーキテクチャ バージョン                      リポジトリ    容量
================================================================================
アップグレード:
 code         x86_64         1.12.1-1493934217.el7           code          59 M

トランザクションの要約
================================================================================
アップグレード  1 パッケージ

総ダウンロード容量: 59 M
これでいいですか? [y/N]: y
パッケージをダウンロードしています:
code-1.12.1-1493934217.el7.x86_64.rpm           6.6 MB/s |  59 MB     00:08    
--------------------------------------------------------------------------------
合計                                            6.5 MB/s |  59 MB     00:09     
トランザクションの確認を実行中...
トランザクションの確認に成功しました。
トランザクションのテストを実行中...
トランザクションのテストに成功しました。
トランザクションを実行中...
  アップグレード: code-1.12.1-1493934217.el7.x86_64                         1/2 
  整理中        : code-1.11.2-1492070635.el7.x86_64                         2/2 
  検証中        : code-1.12.1-1493934217.el7.x86_64                         1/2 
  検証中        : code-1.11.2-1492070635.el7.x86_64                         2/2 

アップグレード済み:
  code.x86_64 1.12.1-1493934217.el7                                             

完了しました!
# dnf install dnf-plugin-system-upgrade
メタデータの期限切れの確認は、0:01:57 時間前の Sat May  6 11:32:25 2017 に実施しました。
依存性が解決されました。
================================================================================
 Package                             アーキテクチャ
                                              バージョン        リポジトリ
                                                                           容量
================================================================================
インストール:
 dnf-plugin-system-upgrade           noarch   0.7.1-4.fc25      updates    48 k
 python3-dnf-plugin-system-upgrade   noarch   0.7.1-4.fc25      updates    31 k

トランザクションの要約
================================================================================
インストール  2 パッケージ

総ダウンロード容量: 79 k
インストールされる容量: 173 k
これでいいですか? [y/N]: y
パッケージをダウンロードしています:
(1/2): python3-dnf-plugin-system-upgrade-0.7.1- 120 kB/s |  31 kB     00:00    
(2/2): dnf-plugin-system-upgrade-0.7.1-4.fc25.n 178 kB/s |  48 kB     00:00    
--------------------------------------------------------------------------------
合計                                             12 kB/s |  79 kB     00:06     
トランザクションの確認を実行中...
トランザクションの確認に成功しました。
トランザクションのテストを実行中...
トランザクションのテストに成功しました。
トランザクションを実行中...
  インストール  : python3-dnf-plugin-system-upgrade-0.7.1-4.fc25.noarch     1/2 
  インストール  : dnf-plugin-system-upgrade-0.7.1-4.fc25.noarch             2/2 
  検証中        : dnf-plugin-system-upgrade-0.7.1-4.fc25.noarch             1/2 
  検証中        : python3-dnf-plugin-system-upgrade-0.7.1-4.fc25.noarch     2/2 

インストール済み:
  dnf-plugin-system-upgrade.noarch 0.7.1-4.fc25                                 
  python3-dnf-plugin-system-upgrade.noarch 0.7.1-4.fc25                         

完了しました!
# dnf system-upgrade download --releasever=26
Fedora 26 - x86_64 - Updates                    1.9 kB/s | 257  B     00:00    
RPM Fusion for Fedora 26 - Nonfree              122 kB/s | 158 kB     00:01    
RPM Fusion for Fedora 26 - Free                 688 kB/s | 529 kB     00:00    
Fedora 26 - x86_64                              6.4 MB/s |  53 MB     00:08    
Failed to synchronize cache for repo 'rpmfusion-free-updates', 無効化。
Failed to synchronize cache for repo 'Dropbox', 無効化。
Failed to synchronize cache for repo 'rpmfusion-nonfree-updates', 無効化。
メタデータの期限切れの確認は、0:01:13 時間前の Sat May  6 11:35:52 2017 に実施しました。
依存性が解決されました。
================================================================================
 Package                         アーキテクチャ
                                        バージョン                 リポジトリ
                                                                           容量
================================================================================
インストール:
 beignet                         x86_64 1.3.1-1.fc26               fedora 4.6 M
 blivet-gui                      noarch 2.1.3-1.fc26               fedora 300 k
 clang-libs                      x86_64 3.9.1-2.fc26               fedora 8.7 M
 cldr-emoji-annotation           noarch 31.0.0_1-1.fc26            fedora 2.0 M
 compat-openssl10                x86_64 1:1.0.2j-6.fc26            fedora 1.1 M
...
...
...
  zlib.x86_64 1.2.11-2.fc26                                                     
  zlib-devel.x86_64 1.2.11-2.fc26                                               
  zziplib.x86_64 0.13.62-8.fc26                                                 

ダウングレード済み:
  blender.x86_64 1:2.78c-1.fc26                                                 
  blender-fonts.noarch 1:2.78c-1.fc26                                           
  inkscape.x86_64 0.92.0-11.fc26                                                
...
...
...

完了しました!
Download complete! Use 'dnf system-upgrade reboot' to start the upgrade.
ダウンロードされたパッケージは、次の成功するトランザクションまで、キャッシュに保存されます。
'dnf clean packages' を実行することでキャッシュを削除できます。
# dnf system-upgrade reboot

最後のリブート処理で、パッケージのアップグレードと整理が始まります。時間はかかりましたが、アップグレードを無事終了することができました。

Fedora 26 の新しい機能などについては別記事でレポートして行く予定です。

参考サイト

  1. Releases/26/Schedule - FedoraProject

 

ブログランキング・にほんブログ村へ
にほんブログ村

2017-04-20

Oracle、8件の脆弱性を修正した「Java SE 8 Update 131」を公開 - 窓の杜

Oracle Corporation は 18 日(現地時間)、Java Platform, Standard Edition(Java SE)の最新版 Java SE 8 Update 131 を公開しました。これは定例更新であるクリティカルパッチアップデート (CPU) で、8 件の脆弱性を修正したものです。

なお、次回の定例セキュリティアップデートは 7 月 18 日に実施される予定だそうです。

参考サイト

  1. Oracle、8件の脆弱性を修正した「Java SE 8 Update 131」を公開 - 窓の杜 [2017-04-19]

 

ブログランキング・にほんブログ村へ
にほんブログ村

2017-03-20

Android Studio と Fedora (2)

Fedora に Android Studio をインストールして、Android アプリを開発する最低限の環境を整えましたが[1]、ひとつ問題が残っていました。それは、Android 端末の実機を、USB を通して接続し、開発したアプリを実機で直接実行することを確認できなかったことでした。もしかすると Linux 版では実機の接続はサポートされていないか、もしくは、今回購入した型落ちの Android 端末 URBANO V02 では、Linux へ接続するのは無理なのかもしれないという不安がありました。

しかしその不安は杞憂でした。Fedora 側で メディア転送プロトコル (MTP, Media Transfer Protocol) をサポートするライブラリをインストールすれば接続できるはずだということが判ったためです。参考サイト [2] にぴったりの説明がありましたので、それにもとづき自分の環境 (Fedora 25 x86_64) で確認した結果を備忘録としてまとめました。

開発者向けオプションの設定 [Android]

まずは、Android 側で「開発者向けオプション」の設定が出来るようにします。デフォルトでは「設定」でこのオプションが非表示になっているので参考資料 [3] に従って表示させます。

とりあえず、「開発者向けオプション」では以下のように設定しました。

 

jmtpfs のインストール [Fedora]

jmtpfs は MTP 対応デバイスへアクセスするためのファイルシステムで、ユーザー空間でファイルシステムを作成する機能を提供する FUSE, Filesystem in Userspace と、MTP を実装したライブラリ libmtp をベースにしています[4]

root 権限で jmtpfs をインストールします。

$ su
パスワード:
# dnf install jmtpfs
...
...

Android 端末を、Fedora が稼働している PC へ USB 接続します。念の為、dmesg コマンドで OS が Android 端末を認識しているかどうか確認します。マウントに成功すると、ファイルの中身を確認できます。

$ dmesg | tail
[ 2413.637244] usb 1-2: Product: KYOCERA_Android
[ 2413.637254] usb 1-2: Manufacturer: KYOCERA
[ 2413.637262] usb 1-2: SerialNumber: dce34c3086
[ 2430.772947] usb 1-2: usbfs: process 4908 (jmtpfs) did not claim interface 0 before use
[ 2430.929832] usb 1-2: reset high-speed USB device number 18 using xhci_hcd
[ 2431.101339] usb 1-2: usbfs: process 4908 (jmtpfs) did not claim interface 0 before use
[ 2431.101621] usb 1-2: usbfs: process 4883 (events) did not claim interface 0 before use
[ 2530.095480] perf: interrupt took too long (4011 > 4005), lowering kernel.perf_event_max_sample_rate to 49000
[ 3314.230265] usb 1-2: usbfs: process 4875 (gvfsd-mtp) did not claim interface 0 before use
[ 3316.737372] perf: interrupt took too long (5016 > 5013), lowering kernel.perf_event_max_sample_rate to 39000
$ 

Android 端末のマウント [Fedora]

root 権限で、マウントポイント(この例では /mnt/android)を作成し、jmtpfs コマンドで Android 端末のファイルシステムをマウントします。

# mkdir /mnt/android
# jmtpfs /mnt/android
Device 0 (VID=0482 and PID=0a74) is UNKNOWN in libmtp v1.1.11.
Please report this VID/PID and the device model to the libmtp development team
Android device detected, assigning default bug flags
# ls /mnt/android
内部ストレージ
# ls /mnt/android/内部ストレージ
Alarms   Download    Movies         Podcasts             com.facebook.orca
Android  Effectplus  Music          Ringtones            kindle
Books    IrDA        Notifications  amazonmp3            media
DCIM     LISMO       Pictures       com.facebook.katana
# 

Android Studio でアプリの実行 [Fedora/Android]

Android 端末のファイルシステムをマウントした状態で、Android Studio でプロジェクトのアプリをコンパイル・実行すると、接続するデバイス、USB 接続した Android 端末とシミュレーター (AVD, Android Virtual Device) のリストが表示されます。

同時に、Android 端末上では下記のメッセージが表示されますので、OK ボタンをタップします。

すると、Fedora の Android Studio 側では認証されたデバイスとして表示されますので、選択して OK ボタンをクリックします。

プロジェクトのアプリがビルドされると、Android 端末へ転送されて起動されます。なお、転送されたアプリ (My Application) は「その他のアプリ」にありました。

 

Android 端末のアンマウント [Fedora]

Fedora にマウントした Android 端末のファイルシステムをアンマウントするには、以下のように fusermount コマンドを使います。

# fusermount -u /mnt/android
# exit

追記 [2017/03/31]

本記事を書いている時に PC と Android を接続するマイクロ USB ケーブルに悩まされていました。それは充電用に使うマイクロ USB コードと、データ通信用のものとを区別せずにごちゃごちゃに使っていためです。結局、データ通信用のケーブルを購入して専用に使うことにしたのですが、この USB ケーブルで Android を接続すれば自動的に Linux 側にマウントされることがわかりました。そもそも既に持っていた(デジカメのデータ通信用)USB ケーブルでも同じ結果になることも確認できました。

当初なぜそれに気が付かなかったのか謎だったので、カーネルのバージョン(現バージョンは kernel-4.10.6-200)を下げるなどして確認したのですが、バージョンを下げても自動的にマウントされることが確認できました。結局、Android の実機でアプリを動かしてみたい一心で、USB ケーブルの混用に悩まされる中で基本的なことをしっかり確認していなかった可能性があります。

ちなみに自動的にマウントされる場所は以下の場所でした。

$ mount
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime,seclabel)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
devtmpfs on /dev type devtmpfs (rw,nosuid,seclabel,size=1962756k,nr_inodes=490689,mode=755)
...
...
...
nfsd on /proc/fs/nfsd type nfsd (rw,relatime)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,seclabel)
/dev/mmcblk0p2 on /boot type ext4 (rw,relatime,seclabel,data=ordered)
/dev/mmcblk0p1 on /boot/efi type vfat (rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=winnt,errors=remount-ro)
/dev/mapper/fedora-home on /home type ext4 (rw,relatime,seclabel,data=ordered)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
tmpfs on /run/user/42 type tmpfs (rw,nosuid,nodev,relatime,seclabel,size=394956k,mode=700,uid=42,gid=42)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,seclabel,size=394956k,mode=700,uid=1000,gid=1000)
gvfsd-fuse on /run/user/1000/gvfs type fuse.gvfsd-fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
fusectl on /sys/fs/fuse/connections type fusectl (rw,relatime)
$ ls /run/user/1000/gvfs
'mtp:host=%5Busb%3A001%2C003%5D'
$ ls /run/user/1000/gvfs/'mtp:host=%5Busb%3A001%2C003%5D'
'Internal storage'
$ ls /run/user/1000/gvfs/'mtp:host=%5Busb%3A001%2C003%5D'/'Internal storage'
Alarms   Download    Movies         Podcasts             com.facebook.orca
Android  Effectplus  Music          Ringtones            kindle
Books    IrDA        Notifications  amazonmp3            media
DCIM     LISMO       Pictures       com.facebook.katana
$ 

参考サイト

  1. bitWalk's: Android Studio と Fedora [2017-03-12]
  2. Linux でAndroid スマートフォンをストレージデバイスとしてマウントする - Qiita [2016-08-22]
  3. アプリを実行する | Android Developers
  4. jmtpfs: Exchanging files between Android devices and Linux | Jacquette Engineering

 

私の Java プログラマ歴は 20 年もありませんが、ぴったりな入門書が発売されましたので早速購入して教科書にしています。

ブログランキング・にほんブログ村へ
にほんブログ村