使ったのはMovieLens 100k。
「100,000 ratings from 1000 users on 1700 movies.」
だそうです。
from sklearn.cluster import KMeans
def main():
_items = []
_f = open('./rating.csv' )
_lines = _f.readlines()
for _line in _lines:
_items.append(_line.split(','))
_f.close()
km = KMeans(init='k-means++')
km.fit(_items)
print(km.labels_)
if __name__ == '__main__':
main()
すげえ簡単。。。
CSVは1行が1人分で全部の映画のレーティング情報(0が観てない、評価は1から5)が入っています。1000ユーザーが1700本の映画を評価(未鑑賞含む)してます。
だいたいこんな感じ。
5,3,4,3,3,5,4,1,5,3,2,5,5,5,5,5,3,4,,,,,,,,
4,0,0,0,0,0,0,0,0,2,0,0,4,4,0,0,0,0,,,,,,,,
得られる結果は
[0 1 4 4 3 2 6 3 4 6 3 7 6 2 1 5 1 6 4 7 1 3 3 7,,,,,,,
インデックス2番のユーザーさんと3番のユーザーさんは好きな映画が似る傾向にありそうですね。
Python 3.4.2、scikit-learn 0.15.2 で試しました。
Clustering text documents using k-means (K平均法を使ってテキスト文書をクラスタリングする)というそのまんまのサンプルがあったので写経して最低限だけ削りだしてみた。
K平均法とかTF-IDFとか潜在意味解析の説明は割愛。
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from sklearn.decomposition import TruncatedSVD
from sklearn.preprocessing import Normalizer
def main():
_items = [
'わたし まけ まし た わ',
'わたし まけ まし た わ',
'わたし まけ まし た わ',
'わたし まけ まし た わ',
'となり の きゃく は よく かき くう きゃく だ',
'にわ には にわ なかにわ には にわ にわとり が いる',
'バカ と テスト と 召喚獣',
'俺 の 妹 が こんな に 可愛い わけ が ない'
]
vectorizer = TfidfVectorizer(
use_idf=True
)
X = vectorizer.fit_transform(_items)
lsa = TruncatedSVD(10)
X = lsa.fit_transform(X)
X = Normalizer(copy=False).fit_transform(X)
km = KMeans(
init='k-means++',
)
km.fit(X)
print(km.labels_)
if __name__ == '__main__':
main()
テキストは分かち書きされてる状態(空白区切りになってます)でドキュメント単位でリストにいれておく。これを元データとしてTfidfVectorizerに突っ込みます。ここでドキュメントがベクトル化されます。
で、潜在意味解析を通した上でK平均法でクラスタリング。至って単純。
km.labels_を出力すると
[1 1 1 1 0 2 4 3]
こんな感じで出力されるのですが、これは「データセットのインデックス0,1,2,3は1番クラスタ、インデックス4は0番クラスタ、、、」ということです。これを使って元データをグルーピングしておきます。
すっごい簡単。使い方はこれであってる、と思う。たぶん。あ、ドキュメント数は少なくても1,000以上ないときれいにクラスタリングされなそうだし、テキストももっと長くないと納得のいく結果は出力されにくいんじゃないかと。
自分のツイートを使ったり青空文庫を使ったりで気軽に試せそうです。
Python 3.4.2、scikit-learn==0.15.2 で動かしました。
昨日Mahoutの記事書いたばっかりなのにね。
ユーザーがアップロードした画像とかをS3に保存したいときに使うメモ。
AWSのAccessKeyとSecretAccessKeyはAWSコンソールにログインして、「右上のアカウント名 > Security Credentials」 で生成しておきます。
pip install boto
S3に投げ込むのはboto(読みはボートー、でいいんだろうか。。。)だけあればOK。Python2.7でもPython3.4でもpipでインストールできました。
$ pip freeze
boto==2.32.1
投げ込むコードは以下
from boto.s3.connection import S3Connection
from boto.s3.key import Key
def main():
print('start')
_s3 = S3Connection(
'AccessKey',
'SecretAccessKey',
)
_bucket = _s3.get_bucket('バケット名称')
_key = Key(_bucket)
_key.set_metadata('Content-Type', 'image/jpeg')
_key.key = 'img.jpg'
_key.set_contents_from_filename('./img.jpg')
if __name__=='__main__':
main()
非常に簡単。
set_metadataは無くてもJpegファイルの場合は問題ないっぽいけど、Content-Typeによっては問題が出たりするのかもしれない。
バケット側のパーミッションとかポリシーとかはまた別の話ということで。
今更感満載なんですけど、最近何度か続いてyaml触ったもんでメモとして。
使うのはPyYAMLです。
pip install pyyaml
Python2でもPython3でも上記で入るはずです。2.7と3.4で試しました。
host: HOSTNAME
port: PORT
dbname: DBNAME
user: USERNAME
passwd: PASSWD
こんなYAMLをDBの接続情報として用意しておいたとして、
import yaml
def main():
_var = open('./settings.yaml').read()
_yaml = yaml.load(_var)
print(_yaml['host'])
if __name__ == "__main__":
main()
読んだYAMLは辞書になってますので、_yaml[キー]で触れます。
ちょっとした設定ファイルとかには便利ですね。
MySQLドライバはどれを使えばいいのかはっきりわからない、というのがPython3に本格的に踏み込めないでいた一番の理由がだったわけですが、MySQL Connector/PythonがPython3をサポートしててDjangoでも使えてマルチバイト文字もちゃんと通るっぽかったので試してみました。
unzip mysql-connector-python-1.2.3.zip
cd mysql-connector-python-1.2.3
python setup.py install
pip freeze
インストールはこれだけ。
DB-API 2.0準拠らしいので触り方も変わらずに安心。こういうのがPythonのいいところじゃないかと。
import mysql.connector
def main():
_conn = mysql.connector.connect(
user='USERNAME',
password='PASSWD',
host='127.0.0.1',
database='DBNAME')
_cur = _conn.cursor()
_cur.execute("select * from app_comment;")
for _row in _cur.fetchall():
print(_row[0])
_cur.close()
_conn.close()
if __name__ == '__main__':
main()
DjangoからMySQLを使うときはこれで。
DATABASES = {
'default': {
'NAME': 'DBNAME',
'ENGINE': 'mysql.connector.django',
'USER': 'USERNAME',
'PASSWORD': 'PASSWD',
}
}
マルチバイト文字使ってもinsert,update、selectひと通り問題なさ気だったので試しになんか書いてみようと思いました。
あ、Djangoは1.7で試してます。
「Python3やんなきゃね」が季節の挨拶じみてきたので久々に重い腰をあげてみました。もう3.4かいな。
Djangoも1.7とか。
sudo wget https://www.python.org/ftp/python/3.4.1/Python-3.4.1.tgz
sudo tar zxfv Python-3.4.1.tgz
cd Python-3.4.1
sudo ./configure --enable-shared
sudo make & make install
sudo vi /etc/ld.so.conf
/usr/local/lib
ldconfig
ここまででPython3.4が起動するようになりました。
試しに
# /usr/local/bin/python3.4
Python 3.4.1 (default, Sep 16 2014, 12:43:31)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
おぉ、できたできた。
ついでに仮想環境も。
mkvirtualenvじゃなくてPython3っぽくvenvを使ってみます。
/usr/local/bin/python3.4 -m venv demo34
source demo34/bin/activate
pip freeze
deactivate
easy_installとの決別です。
気になるのはMySQLのドライバかなー。
CentOSにMeCabをインストールする方法の続きなんですけど、MeCab入れたらPythonから叩くよね、ってことでバインディングもインストールしておきます。
wget https://mecab.googlecode.com/files/mecab-python-0.996.tar.gz
tar zxfv mecab-python-0.996.tar.gz
cd mecab-python-0.996
python setup.py build
python setup.py install
これだけだとimportしたときにエラーが出ます。
ImportError: libmecab.so.2: cannot open shared object file: No such file or directory
そこで、
sudo vi /etc/ld.so.conf
/usr/local/lib #この行を追加
sudo ldconfig
やっとimportできるようになります。
$ python
Python 2.7.7 (default, Jun 4 2014, 17:11:14)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.
>>> import MeCab
Redisは頻繁に使ってます。データベースとして使うって言うよりテンポラリキャッシュとして使うケースのほうが多いです。
import redis
_redis = redis.Redis(
host=REDIS_HOST,
port=REDIS_PORT,
db=REDIS_DB)
_redis.set('key', 'value')
_redis.expire('key', 90)
有効期限の設定方法がわかりにくいというかピンとこなくて悩んだのでメモ。「キーに対してバリューと有効期限を設定する」っていうよりも「キーにバリューを設定、キーに有効期限を設定」っていう2段階、ってイメージでしょうか。
expireで指定する値は秒数。上記で90秒間有効です。
Python 2.7.5、redis 2.9.1(本体じゃなくてパッケージのほう)
ハセテツはこう書いてますよというメモ。
# -*- encoding: utf-8 -*-
class SampleClass(object):
def __init__(self):
self._params = None
@property
def params(self):
return self._params
@params.setter
def params(self, v):
self._params = v
if __name__ == '__main__':
_obj = SampleClass()
_obj.params = {'foo': 'bar'}
print _obj.params
「Pythonの軽量フレームワークBottleを試してみた」の続き。
せっかく調べたので忘れないようにやったことを書いておこう。
# -*- encoding: utf-8 -*-
from bottle import (
run,
default_app,
route,
request,
response
)
@route('/cookie_test')
def cookie_test():
# cookie取得
_stamp = request.get_cookie("_stamp")
if _stamp is None:
response.set_cookie(
"_stamp",
"some value",
max_age=3888000)
return 'Hello.'
if __name__ == "__main__":
run(host="localhost", port=8080, debug=True, reloader=True)
else:
application = default_app()
get_cookieで読み込み、set_cookieで書き込みます。
max_ageは秒数で、上記の例だとcookieの有効期限は45日後です。指定しないとブラウザを閉じた時にcookieは消えます。