ためすう

Rails で String#inquiry を使ってみる

2019-08-10

やったこと

Rails の ActiveSupport で拡張されている String#inquiry を使ってみます。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

$ rails --version
Rails 5.2.3

調査

実行結果

$ rails c
Running via Spring preloader in process 57768
Loading development environment (Rails 5.2.3)
irb(main):001:0> 'prod'.inquiry.prod?
=> true
irb(main):002:0> 'prod'.inquiry.prodfalse?
=> false

参考

sklearn で TF-IDF

2019-08-09

やったこと

TF-IDF を用いて、文書内の単語の重み付けをします。

確認環境

$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
import sklearn
print(sklearn.__version__)
    0.19.0

調査

TF-IDF とは

TF-IDF とは、term frequency-inverse のことで、

TF (単語の出現頻度) X IDF (逆文書頻度) となります。

$$ tf-idf(t,d) = tf(t, d) * idf(t, d) $$

使ってみる

from sklearn.feature_extraction.text import TfidfVectorizer
corpus = [
    'This is the first document.',
    'This document is the second document.',
    'And this is the third one.',
    'Is this the first document?',
]
vec = TfidfVectorizer()
X = vec.fit_transform(corpus)
print(vec.get_feature_names())
print(type(X))
print(X.toarray())

出力結果

['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
<class 'scipy.sparse.csr.csr_matrix'>
[[0.         0.46979139 0.58028582 0.38408524 0.         0.
  0.38408524 0.         0.38408524]
 [0.         0.6876236  0.         0.28108867 0.         0.53864762
  0.28108867 0.         0.28108867]
 [0.51184851 0.         0.         0.26710379 0.51184851 0.
  0.26710379 0.51184851 0.26710379]
 [0.         0.46979139 0.58028582 0.38408524 0.         0.
  0.38408524 0.         0.38408524]]

参考

sklearn の DictVectorizer で one-hot エンコーディングする

2019-08-08

やったこと

カテゴリ特徴を、エンコーディングします。

確認環境

$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
import sklearn
print(sklearn.__version__)
0.19.0

調査

from sklearn.feature_extraction import DictVectorizer
D = [{'name': 'ABC', 'age': 23}, {'name': 'DEF', 'age': 35}, {'name': 'XYZ', 'age': 66}, {'name': 'AAA', 'age': 5}]
v = DictVectorizer(sparse=False)
X = v.fit_transform(D)
print(v.get_feature_names())
print(type(X))
print(X.shape)
print(X)

print('---')

# 疎行列
v2 = DictVectorizer(sparse=True)
X2 = v2.fit_transform(D)
print(X2)
print(v2.get_feature_names())
print(type(X2))
print(X2.shape)
print(X2.toarray())

出力結果

['age', 'name=AAA', 'name=ABC', 'name=DEF', 'name=XYZ']
<class 'numpy.ndarray'>
(4, 5)
[[23.  0.  1.  0.  0.]
 [35.  0.  0.  1.  0.]
 [66.  0.  0.  0.  1.]
 [ 5.  1.  0.  0.  0.]]
---
  (0, 0)	23.0
  (0, 2)	1.0
  (1, 0)	35.0
  (1, 3)	1.0
  (2, 0)	66.0
  (2, 4)	1.0
  (3, 0)	5.0
  (3, 1)	1.0
['age', 'name=AAA', 'name=ABC', 'name=DEF', 'name=XYZ']
<class 'scipy.sparse.csr.csr_matrix'>
(4, 5)
[[23.  0.  1.  0.  0.]
 [35.  0.  0.  1.  0.]
 [66.  0.  0.  0.  1.]
 [ 5.  1.  0.  0.  0.]]

参考

sklearn の CountVectorizer を使う

2019-08-07

やったこと

テキストから単語の数を数えるため、sklearn の CountVectorizer を使ってみます。

確認環境

$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
import sklearn
print(sklearn.__version__)
0.19.0

調査

from sklearn.feature_extraction.text import CountVectorizer
corpus = [
    'This is the first document.',
    'This document is the second document.',
    'And this is the third one.',
    'Is this the first document?',
]
vec = CountVectorizer()
X = vec.fit_transform(corpus)
print(vec.get_feature_names())
print(type(X))
print(X.toarray())

出力結果

['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
<class 'scipy.sparse.csr.csr_matrix'>
[[0 1 1 1 0 0 1 0 1]
 [0 2 0 1 0 1 1 0 1]
 [1 0 0 1 1 0 1 1 1]
 [0 1 1 1 0 0 1 0 1]]

toarray() は 疎行列 -> 配列に変換します。

参考

numpy の multivariate_normal を使ってみる

2019-08-07

やったこと

Numpy で multivariate_normal を使ってみます。

確認環境

$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
import numpy as np
np.__version__
'1.13.1'

調査

共分散

共分散(きょうぶんさん、英: covariance)は、2組の対応するデータ間での、平均からの偏差の積の平均値である

共分散行列

統計学と確率論において、ベクトルの要素間の共分散の行列である。これは、スカラー値をとる確率変数における分散の概念を、多次元に自然に拡張したものである。

やってみる

import numpy as np
mean = [20, 20]
cov = [[5, 0], [25, 25]]
tmp = np.random.multivariate_normal(mean, cov, 3)
aaa, bbb = tmp.T

print(tmp)
print(tmp.T)
print(aaa)
print(bbb)

出力結果

[[22.00279917 18.80819949]
 [21.19539949 21.82857794]
 [18.6510704  19.32493899]]
[[22.00279917 21.19539949 18.6510704 ]
 [18.80819949 21.82857794 19.32493899]]
[22.00279917 21.19539949 18.6510704 ]
[18.80819949 21.82857794 19.32493899]

参考

numpy の vstack、hstack を使ってみる

2019-08-06

やったこと

Numpy で vstack と hstack を使ってみます。

確認環境

$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
import numpy as np
np.__version__
'1.13.1'

調査

import numpy as np
a = np.array([1, 2, 3])
b = np.array([100, 101, 102])
print(np.vstack((a, b)))
print(np.hstack((a, b)))

出力結果

[[  1   2   3]
 [100 101 102]]
[  1   2   3 100 101 102]

参考

Rails に sorbet をインストールしてみる

2019-08-06

やったこと

Rails に sorbet を導入します。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

$ rails --version
Rails 5.2.3

調査

Gemfile

gem 'sorbet', :group => :development
gem 'sorbet-runtime'
$ bundle install

sorbet の初期化

$ bundle exec srb init
# typed: true
class ApplicationController < ActionController::Base
  extend T::Sig

  private
  sig {params(x: Integer).returns(String)}
  def sorbet_init(x)
    # x.to_s
  end
end

型チェックの結果

$ bundle exec srb tc
app/controllers/application_controller.rb:20: Returning value that does not conform to method result type https://srb.help/7005
    20 |  def sorbet_init(x)
    21 |    # x.to_s
    22 |  end
  Expected String
    app/controllers/application_controller.rb:20: Method sorbet_init has return type String
    20 |  def sorbet_init(x)
          ^^^^^^^^^^^^^^^^^^
  Got NilClass originating from:
    app/controllers/application_controller.rb:20:
    20 |  def sorbet_init(x)
          ^^^^^^^^^^^^^^^^^^
Errors: 1

参考

Python の dir を使ってみる

2019-08-05

やったこと

dir 関数を使ってみます。

確認環境

$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
import numpy as np
np.__version__
'1.13.1'

調査

引数がない場合、現在のローカルスコープにある名前のリストを返します。引数がある場合、そのオブジェクトの有効な属性のリストを返そうと試みます。

class Shape:
    def __dir__(self):
        return ['area', 'perimeter', 'location']

s = Shape()
print(dir(s))

出力結果

['area', 'location', 'perimeter']

参考

Ruby で hashie (gem) を使ってみる

2019-08-05

やったこと

今回、gem の hashie を使ってみます。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

調査

インストール

$ gem install hashie

Coercion

データの型を強制します。

require 'hashie'

class BaseCoercionHash < Hash
  include Hashie::Extensions::Coercion
  include Hashie::Extensions::MergeInitializer
end

class DummyJob < BaseCoercionHash
end

class Job < BaseCoercionHash
  coerce_key :name, String
  coerce_key :year, Integer
end

class User < BaseCoercionHash
  coerce_key :name, String
  coerce_key :age, Integer
  coerce_key :job, Job
end


user = User.new(name: 'hogehoge', age: 20)
p user

user2 = User.new(name: 'hogehoge', age: 'ああああ')
p user2

user3 = User.new(name: 'hogehoge', age: 35, job: Job.new(name: 'free'))
p user3


user4 = User.new(name: 'hogehoge', age: 35, job: {name: 'free2'})
p user4

user5 = User.new(name: 'hogehoge', age: 35, job: DummyJob.new)
p user5

user6 = User.new(name: 'hogehoge', age: 35, job: 99999)
p user6

出力結果

ruby-hashie.rb

$ ruby ruby-hashie.rb
{:name=>"hogehoge", :age=>20}
{:name=>"hogehoge", :age=>0}
{:name=>"hogehoge", :age=>35, :job=>{:name=>"free"}}
{:name=>"hogehoge", :age=>35, :job=>{:name=>"free2"}}
{:name=>"hogehoge", :age=>35, :job=>{}}
Traceback (most recent call last):
	8: from ruby-hashie.rb:39:in `<main>'
	7: from ruby-hashie.rb:39:in `new'
	6: from /Users/abc/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/hashie-3.6.0/lib/hashie/extensions/merge_initializer.rb:20:in `initialize'
	5: from /Users/abc/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/hashie-3.6.0/lib/hashie/extensions/merge_initializer.rb:20:in `each'
	4: from /Users/abc/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/hashie-3.6.0/lib/hashie/extensions/merge_initializer.rb:21:in `block in initialize'
	3: from /Users/abc/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/hashie-3.6.0/lib/hashie/extensions/coercion.rb:38:in `set_value_with_coercion'
	2: from /Users/abc/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/hashie-3.6.0/lib/hashie/extensions/coercion.rb:180:in `block in build_coercion'
	1: from /Users/abc/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/hashie-3.6.0/lib/hashie/extensions/coercion.rb:180:in `new'
/Users/abc/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/hashie-3.6.0/lib/hashie/extensions/merge_initializer.rb:20:in `initialize': undefined method `each' for 99999:Integer (NoMethodError)
	6: from ruby-hashie.rb:39:in `<main>'
	5: from ruby-hashie.rb:39:in `new'
	4: from /Users/abc/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/hashie-3.6.0/lib/hashie/extensions/merge_initializer.rb:20:in `initialize'
	3: from /Users/abc/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/hashie-3.6.0/lib/hashie/extensions/merge_initializer.rb:20:in `each'
	2: from /Users/abc/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/hashie-3.6.0/lib/hashie/extensions/merge_initializer.rb:21:in `block in initialize'
	1: from /Users/abc/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/hashie-3.6.0/lib/hashie/extensions/coercion.rb:37:in `set_value_with_coercion'
/Users/abc/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/hashie-3.6.0/lib/hashie/extensions/coercion.rb:40:in `rescue in set_value_with_coercion': Cannot coerce property :job from Integer to Job: undefined method `each' for 99999:Integer (Hashie::CoercionError)

DummyJob クラスが Hash クラスを継承していると、通ってしまいました。

気をつけないと嵌るかもしれません。

参考

numpy.ravel を使ってみる

2019-08-04

やったこと

Numpy で numpy.ravel を使ってみます。

配列を1次元配列にします。

確認環境

$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
import numpy as np
np.__version__
'1.13.1'

調査

import numpy as np
x = np.array([[9, 8, 7], [1, 2, 3], [4, 5, 6]])
print(x.ravel())
print(np.ravel(x))
print(np.reshape(x, -1))

出力結果

[9 8 7 1 2 3 4 5 6]
[9 8 7 1 2 3 4 5 6]
[9 8 7 1 2 3 4 5 6]

参考