TPTブログ

テックポート株式会社のブログです。 技術情報や製品・サービス情報、 また未経験社員がデータサイエンティストを 目指す奮闘記など、更新していきます。

▲心くじけず言語処理100本ノック==05~09==

f:id:TBT_matsu:20200515145048p:plain
こんにちは!
テービーテックの村松です。

「言語処理100本ノック2020]」
nlp100.github.io
に挑戦中!
途中でくじけないか見守ってください・・・。
そして、皆さんも一緒に挑戦してみましょう!

本日は第1章:準備運動05~09です!
間違い・コード改善点などありましたら教えていただけると嬉しいです。

第1章: 準備運動

05.n-gram

「与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ.この関数を用い,”I am an NLPer”という文から単語bi-gram,文字bi-gramを得よ.」

n-gramは自然言語処理でよく使用される単語の切り出し方法の1つです。
文字単位で分解する文字n-gramと単語ごとに分解する単語n-gramがあります。
N個の文字、N個の単語ごとに切り出すのですが、N=1の時ユニグラム(unigram)、N=2の時バイグラム(bigram)、N=3の時トライグラム(trigram)と言います。
今回はバイグラムの問題ですね。

#単語bi-gramの場合
s = 'I am an NLPer'
#単語単位に区切る
words = s.split()
#i個目の単語とi+1個目の単語を取り出していく。
bigram_list = []
for i in range(len(words)-1):
  bigram_list.append((words[i], words[i+1]))
print(bigram_list)
##結果
[('I', 'am'), ('am', 'an'), ('an', 'NLPer')]

次に文字単位での分割をしてみます。
せっかくなのでこちらを使ってみます。

pip install ngram
#文字bi-gramの場合
import ngram
index = ngram.NGram(N=2)
n_list = []
for term in index.ngrams(index.pad(s)):
  n_list.append(term)
print(n_list)
##結果
['$I', 'I ', ' a', 'am', 'm ', ' a', 'an', 'n ', ' N', 'NL', 'LP', 'Pe', 'er', 'r$']
06.集合Permalink

「“paraparaparadise”と”paragraph”に含まれる文字bi-gramの集合を,それぞれ, XとYとして求め,XとYの和集合,積集合,差集合を求めよ.さらに,’se’というbi-gramがXおよびYに含まれるかどうかを調べよ.」

#bi-gramを求める関数の作成
def n_gram(s):
  text = set([s[n:n+2] for n in range(len(s) - 1)])
  return text

_X = 'paraparaparadise'
_Y = 'paragraph'
X = n_gram(_X)
Y = n_gram(_Y)
print(X_n)
print(Y_n)
##結果
{'se', 'ra', 'di', 'ar', 'ad', 'ap', 'pa', 'is'}
{'ra', 'ph', 'ar', 'ag', 'ap', 'pa', 'gr'}
##以降はこの結果(XとY)を使って各集合を求めます。

・和集合:XかYどちらかに含まれる要素を表示します。

#和集合union()
print(X.union(Y))
##結果
{'se', 'ra', 'di', 'ph', 'ar', 'ad', 'gr', 'ag', 'ap', 'pa', 'is'}

・積集合:XとYどちらにも含まれる要素を表示します。

#積集合intersection()
print(X.intersection(Y))
##結果
{'ap', 'ra', 'pa', 'ar'}

・差集合:どちらか片方にのみ含まれる要素を表示します。

#差集合difference()
print(X.difference(Y))
##結果
{'se', 'di', 'is', 'ad'}

・'se'がXとYに含まれているか表示します。

#’se’を含むかどうかを判定
print('Xは', 'se' in X)
print('Yは', 'se' in Y)
##結果
Xは True
Yは False
07.テンプレートによる文生成Permalink

「引数x, y, zを受け取り「x時のyはz」という文字列を返す関数を実装せよ.さらに,x=12, y=”気温”, z=22.4として,実行結果を確認せよ.」

#format()を使用した定型文の作成
def format_text(x, y, z):
  return print('{0}時の{1}は{2}'.format(x,y,z))
x=12
y='気温'
z=22.4
format_text(x, y, z)
##結果
12時の気温は22.4

format()の使い方は以前本日の関数でもご紹介しましたのでご参照くださいませ。

08.暗号文

「与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.
・英小文字ならば(219 - 文字コード)の文字に置換
・その他の文字はそのまま出力
この関数を用い,英語のメッセージを暗号化・復号化せよ.」

def cipher(text):
  result = ''
  for i in text:
    # 小文字か大文字かを区別するislower()
    if i.islower():
      # 文字から文字コードを取得するord()
      # 文字コードから文字を取得するchr()
      result += chr(219 - ord(i))
    else:
      # 英子文字以外はそのまま
      result += i
  return result
s = 'Hello World 2 はろーわーるど'
s_cip = cipher(s)
ans = cipher(s_cip)
print(s_cip)
print(ans)
##結果
Hvool Wliow 2 はろーわーるど
Hello World 2 はろーわーるど
09.Typoglycemia

「スペースで区切られた単語列に対して,各単語の先頭と末尾の文字は残し,それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ.ただし,長さが4以下の単語は並び替えないこととする.適当な英語の文(例えば”I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .”)を与え,その実行結果を確認せよ.」

import random
s = 'I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .'
result = []
for i in s.split():# 単語ごとに4文字以上か判定
  # 4文字以下ならそのまま
  if len(i) <= 4:
    result.append(i)
  else:
    # 4文字以上なら先頭と末尾の文字はそのまま
    # それ以外の文字の順番をランダムに
    m = list(i[1:-1])
    random.shuffle(m)
    # 3つの要素を合体
    result.append(i[0] + ''.join(m) + i[-1])
print(s)
print(' '.join(result))
##結果
I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .
I clnud’ot beievle that I culod alclauty udrsnanted what I was rndaeig : the pmenneaohl pewor of the huamn mind .


ここまでご覧いただきありがとうございました。
以上で第1章終了です。
次回から2章UNIXコマンドです!