Quibako Note

Questions unveiled invite brilliant and keen observation

自然言語処理100本ノック2020(Rev 2)の記録 Chapter 7

自然言語処理100本ノック2020(Rev 2)の記録(Python 3.11)

Chapter 7 単語ベクトル

単語の意味を実ベクトルで表現する単語ベクトル(単語埋め込み)に関して,以下の処理を行うプログラムを作成せよ.

メモ

pip install gensimgensimをインストールする。

ImportError: cannot import name 'triu' from 'scipy.linalg'と怒られたので、 こちらを参考に、Scipyをv1.10.1にする。

60. 単語ベクトルの読み込みと表示

Google Newsデータセット(約1,000億単語)での[学習済み単語ベクトル](https://drive.google.com/file/d/0B7XkCwpI5KDYNlNUTTlSS21pQmM/edit?usp=sharing)(300万単語・フレーズ,300次元)をダウンロードし,”United States”の単語ベクトルを表示せよ.ただし,”United States”は内部的には”United_States”と表現されていることに注意せよ.

メモ

fastText(?)でロードする。下記を参考にしました。

import gensim
model = gensim.models.KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)

print(model["United_States"])
[-3.61328125e-02 -4.83398438e-02  2.35351562e-01  1.74804688e-01
 -1.46484375e-01 -7.42187500e-02 -1.01562500e-01 -7.71484375e-02
  1.09375000e-01 -5.71289062e-02 -1.48437500e-01 -6.00585938e-02
  1.74804688e-01 -7.71484375e-02  2.58789062e-02 -7.66601562e-02
 -3.80859375e-02  1.35742188e-01  3.75976562e-02 -4.19921875e-02
 -3.56445312e-02  5.34667969e-02  3.68118286e-04 -1.66992188e-01
 -1.17187500e-01  1.41601562e-01 -1.69921875e-01 -6.49414062e-02
 -1.66992188e-01  1.00585938e-01  1.15722656e-01 -2.18750000e-01
 -9.86328125e-02 -2.56347656e-02  1.23046875e-01 -3.54003906e-02
 -1.58203125e-01 -1.60156250e-01  2.94189453e-02  8.15429688e-02
  6.88476562e-02  1.87500000e-01  6.49414062e-02  1.15234375e-01
 -2.27050781e-02  3.32031250e-01 -3.27148438e-02  1.77734375e-01
 -2.08007812e-01  4.54101562e-02 -1.23901367e-02  1.19628906e-01
  7.44628906e-03 -9.03320312e-03  1.14257812e-01  1.69921875e-01
 -2.38281250e-01 -2.79541016e-02 -1.21093750e-01  2.47802734e-02
  7.71484375e-02 -2.81982422e-02 -4.71191406e-02  1.78222656e-02
 -1.23046875e-01 -5.32226562e-02  2.68554688e-02 -3.11279297e-02
 -5.59082031e-02 -5.00488281e-02 -3.73535156e-02  1.25976562e-01
  5.61523438e-02  1.51367188e-01  4.29687500e-02 -2.08007812e-01
 -4.78515625e-02  2.78320312e-02  1.81640625e-01  2.20703125e-01
 -3.61328125e-02 -8.39843750e-02 -3.69548798e-05 -9.52148438e-02
 -1.25000000e-01 -1.95312500e-01 -1.50390625e-01 -4.15039062e-02
  1.31835938e-01  1.17675781e-01  1.91650391e-02  5.51757812e-02
 -9.42382812e-02 -1.08886719e-01  7.32421875e-02 -1.15234375e-01
  8.93554688e-02 -1.40625000e-01  1.45507812e-01  4.49218750e-02
 -1.10473633e-02 -1.62353516e-02  4.05883789e-03  3.75976562e-02
 -6.98242188e-02 -5.46875000e-02  2.17285156e-02 -9.47265625e-02
  4.24804688e-02  1.81884766e-02 -1.73339844e-02  4.63867188e-02
 -1.42578125e-01  1.99218750e-01  1.10839844e-01  2.58789062e-02
 -7.08007812e-02 -5.54199219e-02  3.45703125e-01  1.61132812e-01
 -2.44140625e-01 -2.59765625e-01 -9.71679688e-02  8.00781250e-02
 -8.78906250e-02 -7.22656250e-02  1.42578125e-01 -8.54492188e-02
 -3.18359375e-01  8.30078125e-02  6.34765625e-02  1.64062500e-01
 -1.92382812e-01 -1.17675781e-01 -5.41992188e-02 -1.56250000e-01
 -1.21582031e-01 -4.95605469e-02  1.20117188e-01 -3.83300781e-02
  5.51757812e-02 -8.97216797e-03  4.32128906e-02  6.93359375e-02
  8.93554688e-02  2.53906250e-01  1.65039062e-01  1.64062500e-01
 -1.41601562e-01  4.58984375e-02  1.97265625e-01 -8.98437500e-02
  3.90625000e-02 -1.51367188e-01 -8.60595703e-03 -1.17675781e-01
 -1.97265625e-01 -1.12792969e-01  1.29882812e-01  1.96289062e-01
  1.56402588e-03  3.93066406e-02  2.17773438e-01 -1.43554688e-01
  6.03027344e-02 -1.35742188e-01  1.16210938e-01 -1.59912109e-02
  2.79296875e-01  1.46484375e-01 -1.19628906e-01  1.76757812e-01
  1.28906250e-01 -1.49414062e-01  6.93359375e-02 -1.72851562e-01
  9.22851562e-02  1.33056641e-02 -2.00195312e-01 -9.76562500e-02
 -1.65039062e-01 -2.46093750e-01 -2.35595703e-02 -2.11914062e-01
  1.84570312e-01 -1.85546875e-02  2.16796875e-01  5.05371094e-02
  2.02636719e-02  4.25781250e-01  1.28906250e-01 -2.77099609e-02
  1.29882812e-01 -1.15722656e-01 -2.05078125e-02  1.49414062e-01
  7.81250000e-03 -2.05078125e-01 -8.05664062e-02 -2.67578125e-01
 -2.29492188e-02 -8.20312500e-02  8.64257812e-02  7.61718750e-02
 -3.66210938e-02  5.22460938e-02 -1.22070312e-01 -1.44042969e-02
 -2.69531250e-01  8.44726562e-02 -2.52685547e-02 -2.96630859e-02
 -1.68945312e-01  1.93359375e-01 -1.08398438e-01  1.94091797e-02
 -1.80664062e-01  1.93359375e-01 -7.08007812e-02  5.85937500e-02
 -1.01562500e-01 -1.31835938e-01  7.51953125e-02 -7.66601562e-02
  3.37219238e-03 -8.59375000e-02  1.25000000e-01  2.92968750e-02
  1.70898438e-01 -9.37500000e-02 -1.09375000e-01 -2.50244141e-02
  2.11914062e-01 -4.44335938e-02  6.12792969e-02  2.62451172e-02
 -1.77734375e-01  1.23046875e-01 -7.42187500e-02 -1.67968750e-01
 -1.08886719e-01 -9.04083252e-04 -7.37304688e-02  5.49316406e-02
  6.03027344e-02  8.39843750e-02  9.17968750e-02 -1.32812500e-01
  1.22070312e-01 -8.78906250e-03  1.19140625e-01 -1.94335938e-01
 -6.64062500e-02 -2.07031250e-01  7.37304688e-02  8.93554688e-02
  1.81884766e-02 -1.20605469e-01 -2.61230469e-02  2.67333984e-02
  7.76367188e-02 -8.30078125e-02  6.78710938e-02 -3.54003906e-02
  3.10546875e-01 -2.42919922e-02 -1.41601562e-01 -2.08007812e-01
 -4.57763672e-03 -6.54296875e-02 -4.95605469e-02  2.22656250e-01
  1.53320312e-01 -1.38671875e-01 -5.24902344e-02  4.24804688e-02
 -2.38281250e-01  1.56250000e-01  5.83648682e-04 -1.20605469e-01
 -9.22851562e-02 -4.44335938e-02  3.61328125e-02 -1.86767578e-02
 -8.25195312e-02 -8.25195312e-02 -4.05273438e-02  1.19018555e-02
  1.69921875e-01 -2.80761719e-02  3.03649902e-03  9.32617188e-02
 -8.49609375e-02  1.57470703e-02  7.03125000e-02  1.62353516e-02
 -2.27050781e-02  3.51562500e-02  2.47070312e-01 -2.67333984e-02]

61. 単語の類似度

"United States"と”U.S.”のコサイン類似度を計算せよ.

メモ

similarityでコサイン類似度$ C $を計算。定義から下記を直接計算しても同様。

$$ % \require{physics} \begin{equation*} C = \frac{v_1 \cdot v_2}{\norm{v_1}\norm{v_2}} \end{equation*} $$
print(model.similarity("United_States", "U.S."))
0.73107743

62. 類似度の高い単語10件

"United States"とコサイン類似度が高い10語と,その類似度を出力せよ.

メモ

most_similarでコサイン類似度の高い語を順に返してくれる。 引数はベクトルでも、単語でもOK。 単語の場合、入力と同じ単語(ここでは”United_States”)は除いて出力される。

Unites_Statesとか、Untied_Statesとか、誤記が類似度の高い語として抽出された。 同じ文脈で現れるから、それもそうかとも思うけど、U.S.より類似度が高い。。

import numpy as np

v = model["United_States"]
v = v/np.linalg.norm(v) # normalization

print("----- input:vector -----")
for item, value in model.most_similar(v, topn=10):
    print(f"{item}  {value}")

print("----- input:key -----")
for item, value in model.most_similar('United_States', topn=10):
    print(f"{item}  {value}")
----- input:vector -----
United_States  1.0
Unites_States  0.7877248525619507
Untied_States  0.7541370987892151
United_Sates  0.7400724291801453
U.S.  0.7310774326324463
theUnited_States  0.6404393911361694
America  0.6178410053253174
UnitedStates  0.6167312264442444
Europe  0.6132988929748535
countries  0.6044804453849792
----- input:key -----
Unites_States  0.7877248525619507
Untied_States  0.7541370987892151
United_Sates  0.7400724291801453
U.S.  0.7310774326324463
theUnited_States  0.6404393911361694
America  0.6178410053253174
UnitedStates  0.6167312264442444
Europe  0.6132988929748535
countries  0.6044804453849792
Canada  0.601906955242157

63. 加法構成性によるアナロジー

"Spain"の単語ベクトルから”Madrid”のベクトルを引き,”Athens”のベクトルを足したベクトルを計算し,そのベクトルと類似度の高い10語とその類似度を出力せよ.

メモ

ベクトルを規格化する前に加減算する場合と、規格化後に加減算する場合とで、 微妙に異なる結果となる。 most_similarの引数にpositive, negativeのリストを指定する場合は、 規格化後に加減算するものと一致する。 ただし、positive, negativeのリストで指定したと同じ単語(ここでは”Spain”, "Madrid", "Athens")は除いて出力される。

上位に現れる Aristeidis Grigoriadisは、ギリシャの水泳選手。

v1 = model["Spain"]
v2 = model["Madrid"]
v3 = model["Athens"]
pos = ["Spain", "Athens",]
neg = ["Madrid",]

print("----- input:added/subtracted vector(un-normalized) -----")
for item, value in model.most_similar(v1 - v2 + v3, topn=10):
    print(f"{item} {value}")

print("----- input:added/subtracted vector(normalized) -----")
# normalization
v1 = v1/np.linalg.norm(v1)
v2 = v2/np.linalg.norm(v2)
v3 = v3/np.linalg.norm(v3)
for item, value in model.most_similar(v1 - v2 + v3, topn=10):
    print(f"{item} {value}")

print("----- keys -----")
for item, value in model.most_similar(positive=pos, negative=neg, topn=10):
    print(f"{item} {value}")
----- input:added/subtracted vector(un-normalized) -----
Athens 0.7528455853462219
Greece 0.6685472130775452
Aristeidis_Grigoriadis 0.5495778322219849
Ioannis_Drymonakos 0.5361457467079163
Greeks 0.5351786017417908
Ioannis_Christou 0.5330225825309753
Hrysopiyi_Devetzi 0.5088489055633545
Iraklion 0.5059264302253723
Greek 0.5040615797042847
Athens_Greece 0.5034108757972717
----- input:added/subtracted vector(normalized) -----
Athens 0.7548093199729919
Greece 0.6898480653762817
Aristeidis_Grigoriadis 0.560684859752655
Ioannis_Drymonakos 0.555290937423706
Greeks 0.545068621635437
Ioannis_Christou 0.5400862097740173
Hrysopiyi_Devetzi 0.5248445272445679
Heraklio 0.5207759737968445
Athens_Greece 0.516880989074707
Lithuania 0.5166865587234497
----- keys -----
Greece 0.6898480653762817
Aristeidis_Grigoriadis 0.560684859752655
Ioannis_Drymonakos 0.5552908778190613
Greeks 0.545068621635437
Ioannis_Christou 0.5400862097740173
Hrysopiyi_Devetzi 0.5248445272445679
Heraklio 0.5207759737968445
Athens_Greece 0.516880989074707
Lithuania 0.5166865587234497
Iraklion 0.5146791338920593

64. アナロジーデータでの実験

[単語アナロジーの評価データ](https://download.tensorflow.org/data/questions-words.txt) をダウンロードし, vec(2列目の単語) - vec(1列目の単語) + vec(3列目の単語)を計算し, そのベクトルと類似度が最も高い単語と,その類似度を求めよ. 求めた単語と類似度は,各事例の末尾に追記せよ.

メモ

出力は省略するが、加減算後のベクトルも求める。

行頭に:がある行は、見出し?行。アナロジーの分類を示している。 首都-国の関係のアナロジーとか、家族関係のアナロジーとか。 形容詞-副詞のアナロジーなど、文法関係はgramで始まる(grammer?)。

analogies = dict()
buff = []
key = None

with open("questions-words.txt") as f:
    for line in f.readlines():
        ws = line.strip().split()
        if ws[0] == ":":
            if key:
                analogies[key] = buff
                buff = []
            key = ws[1]
        else:
            v1 = model[ws[0]]
            v2 = model[ws[1]]
            v3 = model[ws[2]]

            # normalization
            v1 = v1/np.linalg.norm(v1)
            v2 = v2/np.linalg.norm(v2)
            v3 = v3/np.linalg.norm(v3)

            v0 = v2 - v1 + v3

            rst = model.most_similar(positive=[ws[1], ws[2]], negative=[ws[0]], topn=1)
            pred, sim = rst[0]
            buff.append([*ws, v0, pred, sim])

    analogies[key] = buff

# output
for key, vals in analogies.items():
    print(f"* {key}")
    vals_sorted = sorted(vals, key=lambda v: v[6], reverse=True) # sort by similarity

    for v in vals_sorted[:5]:
        print(f"{v[1]} - {v[0]} + {v[2]} -> {v[5]} (sim={v[6]:.3f}, correct: {v[3]})")
    print("...")
    for v in vals_sorted[-5:]:
        print(f"{v[1]} - {v[0]} + {v[2]} -> {v[5]} (sim={v[6]:.3f}, correct: {v[3]})")
* capital-common-countries
Japan - Tokyo + Moscow -> Russia (sim=0.886, correct: Russia)
Russia - Moscow + Tehran -> Iran (sim=0.878, correct: Iran)
Russia - Moscow + Tokyo -> Japan (sim=0.877, correct: Japan)
Russia - Moscow + Beijing -> China (sim=0.869, correct: China)
Cuba - Havana + Tehran -> Iran (sim=0.864, correct: Iran)
...
Japan - Tokyo + Bern -> Switzerland (sim=0.483, correct: Switzerland)
China - Beijing + Bern -> Bern_NC (sim=0.466, correct: Switzerland)
England - London + Bern -> Hanover (sim=0.453, correct: Switzerland)
Iraq - Baghdad + Bern -> coach_Bobby_Curlings (sim=0.435, correct: Switzerland)
Afghanistan - Kabul + Bern -> Bern_NC (sim=0.423, correct: Switzerland)
* capital-world
Ukraine - Kiev + Moscow -> Russia (sim=0.888, correct: Russia)
Russia - Moscow + Tehran -> Iran (sim=0.878, correct: Iran)
Russia - Moscow + Tokyo -> Japan (sim=0.877, correct: Japan)
Armenia - Yerevan + Baku -> Azerbaijan (sim=0.867, correct: Azerbaijan)
Philippines - Manila + Moscow -> Russia (sim=0.861, correct: Russia)
...
Madagascar - Antananarivo + Bern -> coach_Bobby_Curlings (sim=0.420, correct: Switzerland)
Jordan - Amman + Antananarivo -> Mohamed_Berte (sim=0.413, correct: Madagascar)
Tuvalu - Funafuti + Kingston -> Jamaica (sim=0.407, correct: Jamaica)
Libya - Tripoli + Bern -> Switzerland (sim=0.402, correct: Switzerland)
Greenland - Nuuk + Algiers -> Gulf (sim=0.390, correct: Algeria)
* currency
baht - Thailand + Malaysia -> RM## (sim=0.822, correct: ringgit)
ringgit - Malaysia + Thailand -> baht (sim=0.820, correct: baht)
baht - Thailand + Bulgaria -> leva (sim=0.814, correct: lev)
baht - Thailand + Nigeria -> naira (sim=0.811, correct: naira)
ringgit - Malaysia + Nigeria -> naira (sim=0.806, correct: naira)
...
dong - Vietnam + USA -> lifts_Squaw_Valley (sim=0.376, correct: dollar)
lev - Bulgaria + USA -> lifts_Squaw_Valley (sim=0.376, correct: dollar)
riel - Cambodia + USA -> lifts_Squaw_Valley (sim=0.374, correct: dollar)
dram - Armenia + USA -> Tennent_lager (sim=0.373, correct: dollar)
rial - Iran + USA -> V_Singh_Fij (sim=0.346, correct: dollar)
* city-in-state
Nebraska - Omaha + Wichita -> Kansas (sim=0.825, correct: Kansas)
Michigan - Detroit + Milwaukee -> Wisconsin (sim=0.824, correct: Wisconsin)
Illinois - Chicago + Louisville -> Kentucky (sim=0.819, correct: Kentucky)
Florida - Tampa + Honolulu -> Hawaii (sim=0.817, correct: Hawaii)
Hawaii - Honolulu + Anchorage -> Alaska (sim=0.809, correct: Alaska)
...
Washington - Spokane + Mesa -> Piñon (sim=0.424, correct: Arizona)
Georgia - Atlanta + Irving -> Marilyn_Flax_whose (sim=0.420, correct: Texas)
Washington - Tacoma + Mesa -> Arizona (sim=0.420, correct: Arizona)
Washington - Tacoma + Fontana -> WUSM_SL (sim=0.392, correct: California)
Washington - Spokane + Fontana -> Gus_Guida (sim=0.385, correct: California)
* family
her - his + he -> she (sim=0.944, correct: she)
she - he + his -> her (sim=0.941, correct: her)
granddaughter - grandson + son -> daughter (sim=0.937, correct: daughter)
daughter - son + grandson -> granddaughter (sim=0.937, correct: granddaughter)
daughters - sons + son -> daughter (sim=0.932, correct: daughter)
...
mom - dad + stepbrother -> mother (sim=0.548, correct: stepsister)
policewoman - policeman + stepbrother -> stepfather (sim=0.546, correct: stepsister)
stepsister - stepbrother + groom -> bride (sim=0.544, correct: bride)
stepdaughter - stepson + stepbrother -> niece (sim=0.542, correct: stepsister)
stepmother - stepfather + stepbrother -> sister (sim=0.521, correct: stepsister)
* gram1-adjective-to-adverb
quickly - quick + swift -> swiftly (sim=0.770, correct: swiftly)
fortunately - fortunate + lucky -> luckily (sim=0.767, correct: luckily)
quickly - quick + rapid -> rapidly (sim=0.762, correct: rapidly)
luckily - lucky + fortunate -> fortunately (sim=0.760, correct: fortunately)
usually - usual + typical -> typically (sim=0.753, correct: typically)
...
happily - happy + possible -> humanly_possible (sim=0.390, correct: possibly)
freely - free + possible -> deliberatively (sim=0.385, correct: possibly)
mostly - most + possible -> mainly (sim=0.376, correct: possibly)
freely - free + immediate -> immediately (sim=0.373, correct: immediately)
furiously - furious + immediate -> frantically (sim=0.368, correct: immediately)
* gram2-opposite
inefficient - efficient + productive -> unproductive (sim=0.738, correct: unproductive)
uncomfortable - comfortable + pleasant -> unpleasant (sim=0.737, correct: unpleasant)
illogical - logical + rational -> irrational (sim=0.734, correct: irrational)
unreasonable - reasonable + rational -> irrational (sim=0.722, correct: irrational)
unsure - sure + aware -> unaware (sim=0.714, correct: unaware)
...
impossible - possible + informed -> informing (sim=0.390, correct: uninformed)
impossibly - possibly + responsible -> solely_responsible (sim=0.389, correct: irresponsible)
undecided - decided + possible -> persuadable (sim=0.387, correct: impossible)
uninformative - informative + certain -> predetermined (sim=0.387, correct: uncertain)
uninformative - informative + possible -> humanly_possible (sim=0.387, correct: impossible)
* gram3-comparative
larger - large + big -> bigger (sim=0.848, correct: bigger)
stronger - strong + hard -> harder (sim=0.845, correct: harder)
tighter - tight + tough -> tougher (sim=0.840, correct: tougher)
harder - hard + tough -> tougher (sim=0.834, correct: tougher)
bigger - big + large -> larger (sim=0.834, correct: larger)
...
worse - bad + short -> shorter (sim=0.458, correct: shorter)
newer - new + low -> high (sim=0.453, correct: lower)
worse - bad + new -> thenew (sim=0.452, correct: newer)
greater - great + old -> yearold (sim=0.427, correct: older)
newer - new + wide -> scatter_bomblets (sim=0.397, correct: wider)
* gram4-superlative
strangest - strange + weird -> weirdest (sim=0.827, correct: weirdest)
weirdest - weird + strange -> strangest (sim=0.824, correct: strangest)
strongest - strong + sharp -> sharpest (sim=0.818, correct: sharpest)
lowest - low + high -> highest (sim=0.814, correct: highest)
highest - high + low -> lowest (sim=0.805, correct: lowest)
...
tallest - tall + short -> shortest (sim=0.455, correct: shortest)
oldest - old + fast -> fastest (sim=0.449, correct: fastest)
warmest - warm + quick -> quickest (sim=0.444, correct: quickest)
youngest - young + quick -> quickest (sim=0.444, correct: quickest)
oldest - old + quick -> easiest (sim=0.426, correct: quickest)
* gram5-present-participle
decreasing - decrease + increase -> increasing (sim=0.885, correct: increasing)
implementing - implement + enhance -> enhancing (sim=0.878, correct: enhancing)
increasing - increase + decrease -> decreasing (sim=0.874, correct: decreasing)
singing - sing + swim -> swimming (sim=0.869, correct: swimming)
enhancing - enhance + generate -> generating (sim=0.860, correct: generating)
...
thinking - think + go -> Going (sim=0.471, correct: going)
coding - code + look -> looking (sim=0.461, correct: looking)
thinking - think + say -> Say (sim=0.447, correct: saying)
coding - code + go -> goes (sim=0.443, correct: going)
saying - say + look -> looks (sim=0.440, correct: looking)
* gram6-nationality-adjective
Japanese - Japan + China -> Chinese (sim=0.928, correct: Chinese)
Chinese - China + Japan -> Japanese (sim=0.927, correct: Japanese)
German - Germany + Italy -> Italian (sim=0.926, correct: Italian)
Russian - Russia + Bulgaria -> Bulgarian (sim=0.919, correct: Bulgarian)
Italian - Italy + Germany -> German (sim=0.917, correct: German)
...
English - England + Albania -> Macedonian (sim=0.534, correct: Albanian)
English - England + Austria -> Austrian (sim=0.533, correct: Austrian)
Albanian - Albania + England -> stock_symbol_BNK (sim=0.530, correct: English)
Argentinean - Argentina + England -> ticker_symbol_BNK (sim=0.514, correct: English)
Belorussian - Belarus + England -> stock_symbol_BNK (sim=0.514, correct: English)
* gram7-past-tense
increased - increasing + decreasing -> decreased (sim=0.900, correct: decreased)
decreased - decreasing + increasing -> increased (sim=0.886, correct: increased)
danced - dancing + singing -> sang (sim=0.866, correct: sang)
saw - seeing + taking -> took (sim=0.848, correct: took)
sang - singing + screaming -> screamed (sim=0.847, correct: screamed)
...
fed - feeding + saying -> implying (sim=0.459, correct: said)
went - going + knowing -> hid (sim=0.458, correct: knew)
decreased - decreasing + saying -> stating (sim=0.457, correct: said)
implemented - implementing + saying -> stating (sim=0.455, correct: said)
spent - spending + looking -> look (sim=0.443, correct: looked)
* gram8-plural
horses - horse + dog -> dogs (sim=0.931, correct: dogs)
dogs - dog + horse -> horses (sim=0.926, correct: horses)
cats - cat + dog -> dogs (sim=0.909, correct: dogs)
dogs - dog + cat -> cats (sim=0.898, correct: cats)
cats - cat + horse -> horses (sim=0.883, correct: horses)
...
monkeys - monkey + hand -> hands (sim=0.449, correct: hands)
dollars - dollar + lion -> lions (sim=0.445, correct: lions)
pineapples - pineapple + hand -> hands (sim=0.432, correct: hands)
dollars - dollar + mouse -> Logitech_MX_Revolution (sim=0.432, correct: mice)
mice - mouse + hand -> hands (sim=0.429, correct: hands)
* gram9-plural-verbs
increases - increase + decrease -> decreases (sim=0.878, correct: decreases)
decreases - decrease + increase -> increases (sim=0.878, correct: increases)
provides - provide + generate -> generates (sim=0.862, correct: generates)
generates - generate + provide -> provides (sim=0.852, correct: provides)
provides - provide + enhance -> enhances (sim=0.842, correct: enhances)
...
implements - implement + say -> argue (sim=0.472, correct: says)
talks - talk + see -> negotiations (sim=0.471, correct: sees)
listens - listen + say -> believe (sim=0.464, correct: says)
works - work + say -> argue (sim=0.458, correct: says)
talks - talk + describe -> describing (sim=0.448, correct: describes)

65. アナロジータスクでの正解率

64の実行結果を用い,意味的アナロジー(semantic analogy)と文法的アナロジー(syntactic analogy)の正解率を測定せよ.

メモ

意味的アナロジーは、gramで始まるもの以外。 文法的アナロジーは、gramで始まるもの。

どちらも7割強くらいの正解率。有意かどうかはわからないけど、文法的アナロジーの方が正解率が高い?

cor_sem = 0 # number of correct answer in semantic analogy 
tot_sem = 0 # total number of semantic analogy
cor_syn = 0 # number of correct answer in syntactic analogy
tot_syn = 0 # total number of syntactic analogy

for key, vals in analogies.items():
    if key[:4] == "gram":
        tot_syn += len(vals)
        cor_syn += len(list(filter(lambda v: v[3]==v[5], vals)))
    else:
        tot_sem += len(vals)
        cor_sem += len(list(filter(lambda v: v[3]==v[5], vals)))

# output
print(f"accuracy for semantic analogies: {cor_sem/tot_sem}")
print(f"accuracy for syntactic analogies: {cor_syn/tot_syn}")
accuracy for semantic analogies: 0.7308602999210734
accuracy for syntactic analogies: 0.7400468384074942

66. WordSimilarity-353での評価

[The WordSimilarity-353 Test Collection](https://www.gabrilovich.com/resources/data/wordsim353/wordsim353.html)の評価データをダウンロードし,単語ベクトルにより計算される類似度のランキングと,人間の類似度判定のランキングの間のスピアマン相関係数を計算せよ.

メモ

スピアマン相関係数は、順位データから求められる相関の(ノンパラメトリックな)指標。

$ X,Y $のペアの数を$ N $, 対応する$ X,Y $間の順位差を$ D $とすると、スピアマン相関係数$ \rho _ {XY} $は、次の式で計算できる。

$$ \begin{equation*} \rho_{XY} = 1 - \frac{6\sum D^2}{N^3-N} \end{equation*} $$

scipy.stats.spearmanrで計算可。

zipを展開して得られるcombined.tabには、タブ区切りで単語1,単語2,類似度(人による評価)が入力されている。一行目は凡例。

from scipy.stats import spearmanr

scores_human = []
scores_vector = []

with open("wordsim353/combined.tab") as f:
    for line in f.readlines()[1:]:
        w1, w2, v = line.strip().split()
        scores_human.append(float(v))
        scores_vector.append(model.similarity(w1, w2))

rho, _ = spearmanr(scores_human, scores_vector)
print(rho)        
0.7000166486272194

67. k-meansクラスタリング

国名に関する単語ベクトルを抽出し,k-meansクラスタリングをクラスタ数k=5として実行せよ.

メモ

国連加盟国リストから、スペースをアンダースコアにしてリスト化(countries.txtというファイル名で保存)。"United States of America"は”United_States”ではないけど、とりあえず国連の表記に従う。"Bolivia (Plurinational State of)"などの括弧書きは無視。

from sklearn.cluster import KMeans
from collections import defaultdict

countries = []
vectors = []
with open("countries.txt") as f:
    for line in f.readlines():
        name = line.strip()
        if name in model:
            countries.append(name)
            vectors.append(model[name])

kmeans = KMeans(n_clusters=5).fit(vectors)

# output
clusters = defaultdict(list)
for c, l in zip(countries, kmeans.labels_):
    clusters[l].append(c) 
for i, v in enumerate(clusters.values()):
    print(f"** cluster-{i}: {v}")
** cluster-0: ['Afghanistan', 'Australia', 'Bahrain', 'Bangladesh', 'Bhutan', 'Brunei_Darussalam', 'Cambodia', 'China', 'Egypt', 'India', 'Indonesia', 'Iran', 'Iraq', 'Israel', 'Japan', 'Jordan', 'Kazakhstan', 'Kuwait', 'Kyrgyzstan', 'Lebanon', 'Libya', 'Malaysia', 'Mongolia', 'Morocco', 'Myanmar', 'Nepal', 'Oman', 'Pakistan', 'Qatar', 'Saudi_Arabia', 'Singapore', 'Sri_Lanka', 'Tajikistan', 'Thailand', 'Turkmenistan', 'United_Arab_Emirates', 'Uzbekistan', 'Viet_Nam', 'Yemen']
** cluster-1: ['Albania', 'Andorra', 'Armenia', 'Austria', 'Azerbaijan', 'Belarus', 'Belgium', 'Bulgaria', 'Canada', 'Croatia', 'Cyprus', 'Czech_Republic', 'Denmark', 'Estonia', 'Finland', 'France', 'Georgia', 'Germany', 'Greece', 'Hungary', 'Iceland', 'Ireland', 'Italy', 'Latvia', 'Liechtenstein', 'Lithuania', 'Luxembourg', 'Malta', 'Monaco', 'Montenegro', 'Netherlands', 'Norway', 'Poland', 'Portugal', 'Romania', 'San_Marino', 'Serbia', 'Slovakia', 'Slovenia', 'Spain', 'Sweden', 'Switzerland', 'Turkey', 'Ukraine']
** cluster-2: ['Algeria', 'Angola', 'Benin', 'Botswana', 'Burkina_Faso', 'Burundi', 'Cameroon', 'Chad', 'Comoros', 'Congo', 'Djibouti', 'Equatorial_Guinea', 'Eritrea', 'Ethiopia', 'Gabon', 'Gambia', 'Ghana', 'Guinea', 'Guinea_Bissau', 'Kenya', 'Lesotho', 'Liberia', 'Madagascar', 'Malawi', 'Mali', 'Mauritania', 'Mozambique', 'Namibia', 'Niger', 'Nigeria', 'Rwanda', 'Senegal', 'Somalia', 'South_Africa', 'Sudan', 'Togo', 'Tunisia', 'Uganda', 'Zambia', 'Zimbabwe']
** cluster-3: ['Argentina', 'Bahamas', 'Barbados', 'Belize', 'Bolivia', 'Brazil', 'Cabo_Verde', 'Chile', 'Colombia', 'Costa_Rica', 'Cuba', 'Dominica', 'Dominican_Republic', 'Ecuador', 'El_Salvador', 'Grenada', 'Guatemala', 'Guyana', 'Haiti', 'Honduras', 'Jamaica', 'Mexico', 'Nicaragua', 'Panama', 'Paraguay', 'Peru', 'Philippines', 'Suriname', 'Uruguay', 'Venezuela']
** cluster-4: ['Fiji', 'Kiribati', 'Maldives', 'Marshall_Islands', 'Mauritius', 'Micronesia', 'Nauru', 'New_Zealand', 'Palau', 'Saint_Lucia', 'Samoa', 'Seychelles', 'Solomon_Islands', 'Tonga', 'Tuvalu', 'Vanuatu']

68. Ward法によるクラスタリング

国名に関する単語ベクトルに対し,Ward法による階層型クラスタリングを実行せよ.さらに,クラスタリング結果をデンドログラムとして可視化せよ.

メモ

scikit-learnのAgglomerativeClustering(凝集性クラスタリング、ボトムアップなクラスタリング)のクラスタ間距離のデフォルトはWard

scikit-learnのデンドログラム図示を参考、というかほぼコピペ。

scipyのdendrogramの引数(linkage matrix Z)については、 linkageを参照。 クラスタ数の4成分タプル?のリストで、タプルの1,2成分目は子ノードのクラスタ番号。 クラスタ番号は、leaf nodeを先頭に並べて、子を持つノードはそのあとから並べる形式。 タプルの3成分目は子ノード間の距離。タプルの4成分目はクラスタ内のleaf nodeの数(ここでは、国の数)。 AgglomerativeClustering.childrenは1,2成分目の情報しかないので、 AgglomerativeClustering.distancesを使ってlinkage matrixを作るのが、plot_dendrogram関数。

JapanとChinaが近くにあり(緑ゾーン)、その後Mongoliaや東南アジアの国々とまとめられていくのは、なんとなく納得感*1。 Japanと近そうな韓国があらわれていないのは、正式名称?のRepublic_of_Koreaがモデルに含まれていないということかな。 アメリカ(United_States_of_America)もUnited_Statesにしていないためあらわれていないのと同じ事情かと。 ちゃんと分析するには、このあたりの名寄せとかも必要なんだろうけど、ここではこの辺りで。

from matplotlib import pyplot as plt
from scipy.cluster.hierarchy import dendrogram
from sklearn.cluster import AgglomerativeClustering

def plot_dendrogram(model, **kwargs):
    # Create linkage matrix and then plot the dendrogram

    # create the counts of samples under each node
    counts = np.zeros(model.children_.shape[0])
    n_samples = len(model.labels_)
    for i, merge in enumerate(model.children_):
        current_count = 0
        for child_idx in merge:
            if child_idx < n_samples:
                current_count += 1  # leaf node
            else:
                current_count += counts[child_idx - n_samples]
        counts[i] = current_count

    linkage_matrix = np.column_stack(
        [model.children_, model.distances_, counts]
    ).astype(float)

    # Plot the corresponding dendrogram
    dendrogram(linkage_matrix, **kwargs)


# setting distance_threshold=0 ensures we compute the full tree.
clustering = AgglomerativeClustering(linkage="ward", compute_distances=True).fit(vectors)

plt.figure(figsize=(18, 28))
plt.title("Hierarchical Clustering Dendrogram")
# plot the top three levels of the dendrogram
plot_dendrogram(clustering, orientation="left", labels=countries, leaf_font_size=10)
plt.show()

69. t-SNEによる可視化

ベクトル空間上の国名に関する単語ベクトルをt-SNEで可視化せよ.

メモ

SNEはStochastic Neighbor Embeddingの略。t-SNEは、t分布を使ったもの、ということらしい。 次元削減手法。 類似する点が近くに配置されるように、低次元空間への埋め込みを行う。

色分けはKMeansのグループ分けを使った。 文字が見づらいので、以下を参考に縁取りをした。

import matplotlib.patheffects as patheffects
colors=['tab:blue', 'tab:orange', 'tab:green', 'tab:red', 'tab:purple',]
 
from sklearn.manifold import TSNE

X__embedded = TSNE(n_components=2).fit_transform(np.array(vectors))

plt.scatter(X__embedded[:, 0], X__embedded[:, 1],
            s=3, marker='x', color="gray")
plt.axis("off")
for i, country in enumerate(countries):
    plt.annotate(country, (X__embedded[i, 0], X__embedded[i, 1]),
                 ha="center",
                 size=6,
                 color=colors[kmeans.labels_[i]],
                 path_effects=[patheffects.withStroke(linewidth=2, foreground='whitesmoke', capstyle="round")]
                 )
plt.show()

*1:見えない

自然言語処理100本ノック2020(Rev 2)の記録 Chapter 6

自然言語処理100本ノック2020(Rev 2)の記録(Python 3.11)

Chapter 6 機械学習

本章では,Fabio Gasparetti氏が公開しているNews Aggregator Data Setを用い,ニュース記事の見出しを「ビジネス」「科学技術」「エンターテイメント」「健康」のカテゴリに分類するタスク(カテゴリ分類)に取り組む.

50. データの入手・整形

News Aggregator Data Setをダウンロードし、以下の要領で学習データ(train.txt),検証データ(valid.txt),評価データ(test.txt)を作成せよ.
  1. ダウンロードしたzipファイルを解凍し,readme.txtの説明を読む.
  2. 情報源(publisher)が”Reuters”, "Huffington Post", "Businessweek", "Contactmusic.com", "Daily Mail"の事例(記事)のみを抽出する.
  3. 抽出された事例をランダムに並び替える.
  4. 抽出された事例の80%を学習データ,残りの10%ずつを検証データと評価データに分割し,それぞれtrain.txt,valid.txt,test.txtというファイル名で保存する. ファイルには,1行に1事例を書き出すこととし,カテゴリ名と記事見出しのタブ区切り形式とせよ(このファイルは後に問題70で再利用する).
学習データと評価データを作成したら,各カテゴリの事例数を確認せよ.

メモ

newsCorpora.csvは、次のフォーマットで記載されている。

FORMAT: ID \t TITLE \t URL \t PUBLISHER \t CATEGORY \t STORY \t HOSTNAME \t TIMESTAMP

CATEGORYは、b,t,e,mの4値(b = business, t = science and technology, e = entertainment, m = health)。 ファイルの分割は、scikit-learnのマニュアルを参考に、 sklearn.model_selection.train_test_splitを使う。 train_test_splitは2分割なので、訓練データとその他に分け、その他を検証データと評価データに分ける。

from sklearn.model_selection import train_test_split

PUBS = ["Reuters", "Huffington Post", "Businessweek", "Contactmusic.com", "Daily Mail"]
ext = [] # extracted
with open("newsCorpora.csv") as f:
    for line in f.readlines():
        id_, tit, url, pub, cat, *_ = line.split("\t")
        if pub not in PUBS:
            continue
        ext.append(f"{cat}\t{tit}")

train, valid_test = train_test_split(ext, test_size=0.2, random_state=42)
valid, test = train_test_split(valid_test, test_size=0.5, random_state=42)

with open("train.txt", mode="w") as f:
    for data in train:
        f.write(f"{data}\n")

with open("valid.txt", mode="w") as f:
    for data in valid:
        f.write(f"{data}\n")

with open("test.txt", mode="w") as f:
    for data in test:
        f.write(f"{data}\n")

! head train.txt
e   Lena Dunham: I Feel Prettier With A Naked Face And ChapStick
b   REFILE-FOREX-Yen grinds lower as global stocks rally, dollar holds steady
e   Dolly Parton is a pint-size knickerbocker glittering glory
b   UPDATE 3-Shares of China's JD.com climb in US market debut
e   Seth Rogen talks about Zac Efrons sex appeal on chat show
b   UPDATE 1-Marlboro maker Philip Morris cuts 2014 earnings forecast
b   Walmart Strikes Deal That Will Hopefully Make Organic Food Cheaper
e   Julia Roberts - Julia Roberts opens up about half-sister's death
m   Top Official: VA Has Lost Trust Of Veterans, American People
e   From Cleaning Toilets to Intergalactic Royalty: Jupiter Ascending [Trailer +  ...

51. 特徴量抽出

学習データ,検証データ,評価データから特徴量を抽出し,それぞれtrain.feature.txt,valid.feature.txt,test.feature.txtというファイル名で保存せよ. なお,カテゴリ分類に有用そうな特徴量は各自で自由に設計せよ.記事の見出しを単語列に変換したものが最低限のベースラインとなるであろう.

メモ

「記事の見出しを単語列に変換したもの」は、 例えば、"Saving School Food: A Letter to My (Imaginary) BFF Michelle Obama"なら、 ["Saving", "School", "Food", ...]とする、ということ? 後でロジスティック回帰するので、"Saving"があれば1,なければ0、という特徴量とする、ということ?

ひとまず、これをベースにする。 単複の違いなどをまとめ、冠詞・記号など内容にあまり関しないと思われるものを除くため、形態素解析を行う。 形態素解析にはspaCyのモデルen_core_web_smを使った。 python -m spacy download en_core_web_smでダウンロード可。 モデルについてはこちらを参照。モデル末尾のsmはサイズ(small)を表す。

形態素解析の後、名詞、動詞などを抽出し、その原形(lemma_)のリストに変換する。 除く品詞は、以下。NUM(数詞)については、0に変換した。

  • ADP 設置詞(前置詞など)
  • CCONJ 接続詞
  • DET 限定詞(冠詞など)
  • INTJ 間投詞
  • PART 助詞(notなど)
  • PUNCT 句読点
  • SCONJ 連結詞
  • SPACE 空白
  • SYM 記号
  • X その他

Saving School Foodなど大文字で始まる語は品詞がPROPN(固有名詞)として扱われがちのようなので、 小文字に統一してからspaCyにかけることにした。michelle obamaなどはちゃんと固有名詞として抽出される。 (一部.-などの記号が名詞、形容詞などとして抽出されるが、とりあえずそのまま)

タイトル文字列から単語列に変換する関数title2wordsを定義。 行の先頭にカテゴリを出力し、タブ区切りで特徴量(単語リスト)を出力する。

import spacy
nlp = spacy.load("en_core_web_sm")

def title2words(title ,nlp):
    doc = nlp(title.lower())
    buff = set()
    for token in doc:
        if token.pos_ in elim:
            continue
        elif token.pos_ == "NUM":
            buff.add("0")
        else:
            buff.add(token.lemma_)
    return buff

elim = ["ADP", "CCONJ", "DET", "INTJ", "PART", "PUNCT", "SCONJ", "SPACE", "SYM", "X"]
def extract_feature(inp_file, out_file):
    with open(inp_file, mode="r") as fr, open(out_file, mode="w") as fw:
        for line in fr.readlines():
            cat, tit = line.strip().split("\t")
            words = title2words(tit, nlp)
            fw.write(cat+"\t"+"\t".join(words)+"\n")

extract_feature("train.txt", "train.feature.txt")
extract_feature("valid.txt", "valid.feature.txt")
extract_feature("test.txt",   "test.feature.txt")

! head train.feature.txt
e   feel    naked   chapstick   pretty  face    dunham  I   lena
b   dollar  low stock   hold    steady  forex   refile  global  grind   rally   yen
e   glitter knickerbocker   size    glory   be  parton  pint    dolly
b   0   share   climb   china   debut   update  we  market  jd.com
e   efron   zac sex chat    show    appeal  seth    rogen   talk
b   marlboro    maker   philip  0   forecast    earning cut update  morris
b   hopefully   cheap   deal    walmart strike  that    organic food    will    make
e   julia   about   half    sister  death   roberts open
m   trust   people  lose    official    top veteran american    va  have
e   toilet  trailer intergalactic   jupiter clean   ascend  royalty

52. 学習

51で構築した学習データを用いて,ロジスティック回帰モデルを学習せよ.

メモ

ロジスティック回帰:予測確率を$ p $、特徴量を$ x _ i $とすると、次の式であらわされる。$ w _ i $は重み、$ w _ 0 $は定数項($ x _ 0=1 $)。

$$ %\require{physics} \begin{equation*} p = \frac{1}{1+\exp\qty(-\sum_{i=0}^n w_i x_i)} \end{equation*} $$

scikit-learnマニュアルを参考に、 sklearn.linear_model.LogisticRegressionを使う。 複数クラスへの分類にも対応。

train.feature.txtに抽出された単語のリストをkeysとして、 keys中の語がタイトル(から抽出された単語列)に含まれているかどうかの真偽値を入力Xtrainとした。

from sklearn.linear_model import LogisticRegression
import itertools

def conv(words, keys):
    return [k in words for k in keys]

def cats_X(inp_file, keys=None):
    features = []
    categories = []
    with open(inp_file, mode="r") as f:
        for line in f.readlines():
            category, *feature = line.strip().split("\t")
            categories.append(category)
            features.append(feature)
    if keys is None:
        keys = sorted(set(itertools.chain.from_iterable(features)))
    return categories, [conv(f, keys) for f in features], keys

categories_train, Xtrain, keys = cats_X("train.feature.txt")

clf = LogisticRegression().fit(Xtrain, categories_train)

53. 予測

52で学習したロジスティック回帰モデルを用い,与えられた記事見出しからカテゴリとその予測確率を計算するプログラムを実装せよ.

メモ

テストには、適当に選択した以下の2文を用いた。

  • healthカテゴリ:"Saving School Food: A Letter to My (Imaginary) BFF Michelle Obama"
  • businessカテゴリ:"Daum Communications says to merge with Kakao Corp"
import numpy as np

titles = [
    "Saving School Food: A Letter to My (Imaginary) BFF Michelle Obama",
    "Daum Communications says to merge with Kakao Corp",
]

cat_dict = {
    "b" : "business",
    "t" : "science and technology",
    "e" : "entertainment",
    "m" : "health",
}

Xtemp = [conv(title2words(title, nlp), keys) for title in titles]
pcats = clf.predict(Xtemp)
probs = clf.predict_proba(Xtemp)
classes = list(clf.classes_)
for t, c, p in zip(titles, pcats, probs):
    cat = cat_dict[c]
    prob = p[classes.index(c)]
    print(f"category:{cat},  probability={prob}, title=\"{t}\"")
category:health,  probability=0.8023492088168461, title="Saving School Food: A Letter to My (Imaginary) BFF Michelle Obama"
category:business,  probability=0.903406523772049, title="Daum Communications says to merge with Kakao Corp"

54. 正解率の計測

52で学習したロジスティック回帰モデルの正解率を,学習データおよび評価データ上で計測せよ.
categories_test, Xtest, _ = cats_X("test.feature.txt", keys)
print(f"train data: {clf.score(Xtrain, categories_train)}")
print(f"test data: {clf.score(Xtest, categories_test)}")
train data: 0.9930737551478847
test data: 0.9191616766467066

55. 混同行列の作成

52で学習したロジスティック回帰モデルの混同行列(confusion matrix)を,学習データおよび評価データ上で作成せよ.

メモ

実際のカテゴリ$ x $をカテゴリ$ y $と予測した数$ N _ {xy}\ (x,y={\mathrm{b}, \mathrm{e}, \mathrm{m}, \mathrm{t}}) $を成分とした行列。 対角成分が正解を、非対角成分が不正解を表す。

%matplotlib inline
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay

predicts_train = clf.predict(Xtrain)
predicts_test = clf.predict(Xtest)

cm_train = confusion_matrix(categories_train, predicts_train, labels=classes)
cm_test = confusion_matrix(categories_test, predicts_test, labels=classes)

disp_train = ConfusionMatrixDisplay(confusion_matrix=cm_train,
                                    display_labels=classes)
disp_test  = ConfusionMatrixDisplay(confusion_matrix=cm_test,
                                    display_labels=classes)


fig, axs = plt.subplots(2)

fig.suptitle("Confusion matrices")
plt.subplots_adjust(hspace=0.5)

axs[0].set_title("train_data")
disp_train.plot(ax=axs[0])

axs[1].set_title("test_data")
disp_test.plot(ax=axs[1])

plt.show()

56. 適合率,再現率,F1スコアの計測

52で学習したロジスティック回帰モデルの適合率,再現率,F1スコアを,評価データ上で計測せよ. カテゴリごとに適合率,再現率,F1スコアを求め,カテゴリごとの性能をマイクロ平均(micro-average)とマクロ平均(macro-average)で統合せよ.

メモ

以下を参考にした。

  • カテゴリ$ x $の適合率(precision, $ p _ x $)は、カテゴリ$ x $と予測した中で、実際にカテゴリ$ x $であった割合。上記の混同行列の場合、縦に合計した数のうち、正解$ N _ {xx} $(対角線上の値)の割合。
    $$ \begin{equation*} p_x = \frac{N_{xx}}{\sum_y N_{yx}} \end{equation*} $$
  • カテゴリ$ x $の再現率(recall, $ r _ x $)は、実際にカテゴリ$ x $であった中で、カテゴリ$ x $と予測した割合。上記の混同行列の場合、横に合計した数のうち、正解$ N _ {xx} $(対角線上の値)の割合。
    $$ \begin{equation*} r_x = \frac{N_{xx}}{\sum_y N_{xy}} \end{equation*} $$
  • カテゴリ$ x $のF1スコア$ F _ x $は、適合率および再現率の調和平均。
    $$ \begin{equation*} \frac1{F_x} = \frac12 \qty(\frac1{p_x} + \frac1{r_x}) \end{equation*} $$
  • 適合率$ p _ x $のマクロ平均$ {\langle p \rangle} _ \mathrm{macro} $は、各カテゴリの性能の単純な算術平均($ N _ c=4 $はカテゴリ数)。再現率$ r _ x $などについても同様に計算。
    $$ \begin{equation*} {\langle p \rangle}_\mathrm{macro} = \frac1{N_c} \sum_x p_x \end{equation*} $$
  • マイクロ平均は、混合行列全体で計算を行う。正解(対角要素)の割合に対応。適合率、再現率、F1スコアともに同じ値になる。
    $$ \begin{equation*} {\langle p \rangle}_\mathrm{micro} = \frac{\sum_x N_{xx}}{\sum_{x, y} N_{xy}} \end{equation*} $$

sklearn.metrics.precision_recall_fscore_supportで各スコアを計算してくれる。 図示した混合行列の値から電卓で計算した値とも一致、上記理解でよさそう。

from sklearn.metrics import precision_recall_fscore_support

ptrains, rtrains, ftrains, _ \
    = precision_recall_fscore_support(categories_train,
                                      predicts_train,
                                      labels=classes)
ptrain_micro, rtrain_micro, ftrain_micro, _ \
    = precision_recall_fscore_support(categories_train,
                                      predicts_train,
                                      average="micro",
                                      labels=classes)
ptrain_macro, rtrain_macro, ftrain_macro, _ \
    = precision_recall_fscore_support(categories_train,
                                      predicts_train,
                                      average="macro",
                                      labels=classes)

ptests, rtests, ftests, _ \
    = precision_recall_fscore_support(categories_test,
                                      predicts_test,
                                      labels=classes)
ptest_micro, rtest_micro, ftest_micro, _ \
    = precision_recall_fscore_support(categories_test,
                                      predicts_test,
                                      average="micro",
                                      labels=classes)
ptest_macro, rtest_macro, ftest_macro, _ \
    = precision_recall_fscore_support(categories_test,
                                      predicts_test,
                                      average="macro",
                                      labels=classes)

print("train_data")
for i, c in enumerate(classes):
    print(f"  {cat_dict[c]}")
    print(f"    {ptrains[i]} (precision)")
    print(f"    {rtrains[i]} (recall)")
    print(f"    {ftrains[i]} (F1)")
print(f"  micro average")
print(f"    {ptrain_micro} (precision)")
print(f"    {rtrain_micro} (recall)")
print(f"    {ftrain_micro} (F1)")
print(f"  macro average")
print(f"    {ptrain_macro} (precision)")
print(f"    {rtrain_macro} (recall)")
print(f"    {ftrain_macro} (F1)")

print("test_data")
for i, c in enumerate(classes):
    print(f"  {cat_dict[c]}")
    print(f"    {ptests[i]} (precision)")
    print(f"    {rtests[i]} (recall)")
    print(f"    {ftests[i]} (F1)")
print(f"  micro average")
print(f"    {ptest_micro} (precision)")
print(f"    {rtest_micro} (recall)")
print(f"    {ftest_micro} (F1)")
print(f"  macro average")
print(f"    {ptest_macro} (precision)")
print(f"    {rtest_macro} (recall)")
print(f"    {ftest_macro} (F1)")
train_data
  business
    0.9923413566739606 (precision)
    0.9949539271610356 (recall)
    0.9936459246275198 (F1)
  entertainment
    0.9950506716945557 (precision)
    0.9978728432994564 (recall)
    0.99645975926363 (F1)
  health
    0.9985590778097982 (precision)
    0.9871794871794872 (recall)
    0.9928366762177651 (F1)
  science and technology
    0.9855564995751912 (precision)
    0.972338642078793 (recall)
    0.9789029535864979 (F1)
  micro average
    0.9930737551478847 (precision)
    0.9930737551478847 (recall)
    0.9930737551478847 (F1)
  macro average
    0.9928769014383765 (precision)
    0.988086224929693 (recall)
    0.9904613284238531 (F1)
test_data
  business
    0.9213286713286714 (precision)
    0.9444444444444444 (recall)
    0.9327433628318584 (F1)
  entertainment
    0.9341637010676157 (precision)
    0.9776536312849162 (recall)
    0.9554140127388535 (F1)
  health
    0.9302325581395349 (precision)
    0.7619047619047619 (recall)
    0.837696335078534 (F1)
  science and technology
    0.8275862068965517 (precision)
    0.7058823529411765 (recall)
    0.7619047619047619 (F1)
  micro average
    0.9191616766467066 (precision)
    0.9191616766467066 (recall)
    0.9191616766467066 (F1)
  macro average
    0.9033277843580934 (precision)
    0.8474712976438248 (recall)
    0.871939618138502 (F1)

57. 特徴量の重みの確認

52で学習したロジスティック回帰モデルの中で,重みの高い特徴量トップ10と,重みの低い特徴量トップ10を確認せよ.

メモ

各特徴量の重み(係数)はLogisticRegressioncoef_に格納されている。

重みはカテゴリごとに設定され、次のように解釈できる。

  • 正の重みが大きい単語は、そのカテゴリと関連の高いもの(例えば、"kardashian"(キム・カーダシアン?)ならエンタメカテゴリ(e)の可能性大)
  • 負の重みが大きい単語は、そのカテゴリを排除できるくらい遠いという点で関連性が高い(例えば、"nintendo"ならビジネスカテゴリの可能性が低い(エンタメカテゴリの可能性が大きい))
  • 重みの絶対値が小さい単語は、そのカテゴリと判定するにもそのカテゴリを排除するにも決めてとして弱い(例えば、エンタメカテゴリの”lawyer”(弁護士)なら、ビジネス絡みでも出る単語だし、セレブリティ?の裁判?などの話題(ゴシップ記事?)でも出る単語なので、なんとも言えない。とか?)

ということで、正側のトップ10、負側のトップ10、絶対値の小さいトップ10を表示する。

for i, c in enumerate(classes):
    signed_coeff = sorted(zip(keys, clf.coef_[i]), key=lambda x : x[1], reverse=True)
    abs_coeff = sorted(zip(keys, clf.coef_[i]), key=lambda x : abs(x[1]))
    print(f"---- category: {cat_dict[c]} ----")
    print("- top 10 features (positive weight)")
    for rank, feature in enumerate(signed_coeff[:10], start=1):
        print(f"{rank:2} {feature[0]:15} {feature[1]:.3f}")
    print("- top 10 features (negative weight)")
    for rank, feature in enumerate(reversed(signed_coeff[-10:]), start=1):
        print(f"{rank:2} {feature[0]:15} {feature[1]:.3f}")
    print("- smallest-weight 10 features")
    for rank, feature in enumerate(abs_coeff[:10], start=1):
        print(f"{rank:2} {feature[0]:15} {feature[1]:.3f}")
---- category: business ----
- top 10 features (positive weight)
 1 bank            1.919
 2 fed             1.902
 3 ecb             1.804
 4 obamacare       1.622
 5 ukraine         1.603
 6 mcdonald        1.543
 7 china           1.523
 8 euro            1.512
 9 yellen          1.502
10 piketty         1.459
- top 10 features (negative weight)
 1 aereo           -1.588
 2 victim          -1.270
 3 nintendo        -1.148
 4 heartbleed      -1.094
 5 ebola           -1.090
 6 she             -1.040
 7 star            -1.013
 8 review          -1.002
 9 child           -0.999
10 her             -0.983
- smallest-weight 10 features
 1 politic         0.000
 2 recall          -0.000
 3 reassure        -0.000
 4 withdraw        -0.000
 5 speaker         -0.000
 6 renew           0.001
 7 vado            -0.001
 8 hospitalisation -0.001
 9 tender          0.001
10 accentuate      -0.001
---- category: entertainment ----
- top 10 features (positive weight)
 1 kardashian      1.812
 2 chris           1.788
 3 film            1.525
 4 star            1.445
 5 wedding         1.439
 6 movie           1.394
 7 miley           1.367
 8 canne           1.326
 9 award           1.314
10 trailer         1.304
- top 10 features (negative weight)
 1 google          -1.609
 2 apple           -1.363
 3 china           -1.348
 4 gm              -1.320
 5 facebook        -1.256
 6 microsoft       -1.220
 7 risk            -1.168
 8 ceo             -1.144
 9 recall          -1.141
10 buy             -1.127
- smallest-weight 10 features
 1 shine           -0.000
 2 lawyer          -0.000
 3 joint           0.000
 4 yr              0.000
 5 g               -0.000
 6 y               0.000
 7 bone            -0.000
 8 coach           -0.000
 9 tourism         0.000
10 thai            -0.000
---- category: health ----
- top 10 features (positive weight)
 1 ebola           2.628
 2 fda             2.028
 3 study           2.013
 4 cancer          1.989
 5 doctor          1.951
 6 mer             1.817
 7 medical         1.763
 8 drug            1.719
 9 cigarette       1.544
10 brain           1.536
- top 10 features (negative weight)
 1 gm              -0.970
 2 google          -0.878
 3 dimon           -0.844
 4 facebook        -0.786
 5 climate         -0.769
 6 deal            -0.736
 7 apple           -0.720
 8 fund            -0.641
 9 book            -0.640
10 game            -0.637
- smallest-weight 10 features
 1 bear            -0.000
 2 lagging         -0.000
 3 rapid           -0.000
 4 agricultural    -0.000
 5 fortifie        -0.000
 6 subside         -0.000
 7 blige           -0.000
 8 toned           -0.000
 9 slit            -0.000
10 cicc            -0.000
---- category: science and technology ----
- top 10 features (positive weight)
 1 google          2.807
 2 apple           2.695
 3 facebook        2.671
 4 climate         2.623
 5 microsoft       2.507
 6 tesla           2.038
 7 moon            1.770
 8 comcast         1.741
 9 nasa            1.708
10 heartbleed      1.704
- top 10 features (negative weight)
 1 surge           -0.973
 2 grow            -0.933
 3 drug            -0.898
 4 close           -0.858
 5 still           -0.832
 6 american        -0.821
 7 jump            -0.783
 8 acquisition     -0.779
 9 percent         -0.778
10 cancer          -0.757
- smallest-weight 10 features
 1 upcoming        0.000
 2 maybe           -0.000
 3 toned           -0.000
 4 slender         -0.000
 5 largesse        -0.000
 6 sideboob        -0.000
 7 valentino       -0.000
 8 ninth           -0.000
 9 blige           -0.000
10 begging         -0.000

58. 正則化パラメータの変更

ロジスティック回帰モデルを学習するとき,正則化パラメータを調整することで,学習時の過学習(overfitting)の度合いを制御できる. 異なる正則化パラメータでロジスティック回帰モデルを学習し,学習データ,検証データ,および評価データ上の正解率を求めよ. 実験の結果は,正則化パラメータを横軸,正解率を縦軸としたグラフにまとめよ.

メモ

LogisticRegressionの正則化のデフォルトは$ L _ 2 $正則化。

Cは正則化パラメータの逆数。Cが大きいほど正則化の要請は弱くなるので、過学習は進みやすくなる。

正則化パラメータを大きくする(正則化を弱める)と学習データ(訓練データ)の正解率は単調に大きくなるが、 ある程度のCを超えると過学習が進んで検証データ、評価データの正解率は低下していることが確認できる。

categories_valid, Xvalid, _ = cats_X("valid.feature.txt", keys)

nC = 20
Cs = np.logspace(-1,2,num=nC)
score_train = np.zeros(nC)
score_valid = np.zeros(nC)
score_test = np.zeros(nC)

for i, C in enumerate(Cs):
    clf = LogisticRegression(C=C).fit(Xtrain, categories_train)
    score_train[i] = clf.score(Xtrain, categories_train)
    score_valid[i] = clf.score(Xvalid, categories_valid)
    score_test[i] = clf.score(Xtest, categories_test)

plt.xlabel("Regularization parameter C")
plt.ylabel("score")
plt.xscale("log")

plt.plot(Cs, score_train, label="train_data")
plt.plot(Cs, score_valid, label="valid_data")
plt.plot(Cs, score_test, label="test_data")
plt.legend(["train_data", "valid_data", "test_data"])

plt.show()

59. ハイパーパラメータの探索

学習アルゴリズムや学習パラメータを変えながら,カテゴリ分類モデルを学習せよ. 検証データ上の正解率が最も高くなる学習アルゴリズム・パラメータを求めよ. また,その学習アルゴリズム・パラメータを用いたときの評価データ上の正解率を求めよ.

メモ

「学習アルゴリズム」がロジスティック回帰以外のモデル(SVCとか)を含むのか、 ロジスティック回帰の中の色々な学習方法を指しているのか、不明。。 ここでは、検証データを固定した場合(58.)と交差検証とを比較した*1。 検証データを固定した場合は、58.の結果を用いて、以下の通り。

# fixed validation data
idx = np.argmax(score_valid)

print("fixed validation data (Knock 58)")
print(f"score: {score_test[idx]}")
print(f"C: {Cs[idx]}")
fixed validation data (Knock 58)
score: 0.9221556886227545
C: 2.636650898730358

訓練データから交差検証する場合、LogisticRegressionCVでパラメータ決定できる。 データのうち訓練に用いるものと検証に用いるものをどう選ぶかについては、例えば以下のものがある。他にもLeaveOneOutなどもあるが、今回は省略。

  • KFold:データをK個に分割し、0回目は「0番目の分割を検証データ、残りを訓練データ」とし、1回目は「1番目の分割を検証データ、残りを訓練データ」とし、…という感じ。
  • ShuffleSplit:データをランダムに並べ替えて、そのうちのtest_size分だけ検証データに使用、残りを訓練データとする。これをn_splitsだけ行う。重複してもOK。
  • PredefinedSplit:分割をtest_foldで事前定義する。-1なら検証データに使用しない、0なら0回目の検証データ、1なら1回目の検証データ、…という感じ。

具体的には、以下のようになる。

from sklearn.model_selection import PredefinedSplit, ShuffleSplit, KFold

X = np.arange(6)
test_fold=[1,0,1,-1,0,-1]
n_splits=3
test_size=0.2

cvs = [
    KFold(n_splits=n_splits),
    ShuffleSplit(n_splits=n_splits, test_size=test_size),
    PredefinedSplit(test_fold),
    ]
names = [
    f"KFold(n_splits={n_splits})",
    f"ShuffleSplit(n_splits={n_splits}, test_size={test_size})",
    f"PredefinedSplit(test_fold={test_fold})",
    ]

print(f"X={X}")
for cv, name in zip(cvs, names):
    print(name)
    for i,d in enumerate(cv.split(X)):
        t,v = d
        print(f"  {i}-th iteration; train:{t}, valid:{v}")
X=[0 1 2 3 4 5]
KFold(n_splits=3)
  0-th iteration; train:[2 3 4 5], valid:[0 1]
  1-th iteration; train:[0 1 4 5], valid:[2 3]
  2-th iteration; train:[0 1 2 3], valid:[4 5]
ShuffleSplit(n_splits=3, test_size=0.2)
  0-th iteration; train:[0 4 2 3], valid:[5 1]
  1-th iteration; train:[2 5 0 4], valid:[3 1]
  2-th iteration; train:[2 0 1 4], valid:[5 3]
PredefinedSplit(test_fold=[1, 0, 1, -1, 0, -1])
  0-th iteration; train:[0 2 3 5], valid:[1 4]
  1-th iteration; train:[1 3 4 5], valid:[0 2]

58.のように検証データを固定した場合は、訓練データと検証データのデータ点数が8:1なので、 交差検証(ShuffleSplit)では訓練データと検証データを混ぜたうえで、テストサイズを1/9=0.111とする。

PredefinedSplitで検証データ固定の場合も再現したつもりだったが、 scoreの計算の仕方などが違うのか、使い方が違うのか、58.と合致しなかった。

# cross validation
from sklearn.model_selection import PredefinedSplit, ShuffleSplit, KFold
from sklearn.linear_model import LogisticRegressionCV

# PredefinedSplit (fixed validation data)
test_fold = [-1]*len(categories_train) + [0]*len(categories_valid)

Xtrain = Xtrain + Xvalid
categories_train = categories_train + categories_valid

clf = LogisticRegressionCV(Cs=Cs,
                           cv=PredefinedSplit(test_fold),
                           ).fit(Xtrain, categories_train)
print("PredefinedSplit")
print(f"score: {clf.score(Xtest, categories_test)}")
print(f"C: {clf.C_}")

# ShuffleSplit (3-splits)
clf = LogisticRegressionCV(Cs=Cs,
                           cv=ShuffleSplit(n_splits=3, test_size=0.111),
                           ).fit(Xtrain, categories_train)
print("ShuffleSplit (n_splits=3)")
print(f"score: {clf.score(Xtest, categories_test)}")
print(f"C: {clf.C_}")

# ShuffleSplit (5-splits)
clf = LogisticRegressionCV(Cs=Cs,
                           cv=ShuffleSplit(n_splits=5, test_size=0.111),
                           ).fit(Xtrain, categories_train)
print("ShuffleSplit (n_splits=5)")
print(f"score: {clf.score(Xtest, categories_test)}")
print(f"C: {clf.C_}")

# KFold (5-fold)
clf = LogisticRegressionCV(Cs=Cs,
                           cv=KFold(n_splits=5),
                           ).fit(Xtrain, categories_train)
print("KFold (n_splits=5)")
print(f"score: {clf.score(Xtest, categories_test)}")
print(f"C: {clf.C_}")
PredefinedSplit
score: 0.9206586826347305
C: [5.45559478 5.45559478 5.45559478 5.45559478]
ShuffleSplit (n_splits=3)
score: 0.9206586826347305
C: [16.23776739 16.23776739 16.23776739 16.23776739]
ShuffleSplit (n_splits=5)
score: 0.9214071856287425
C: [5.45559478 5.45559478 5.45559478 5.45559478]
KFold (n_splits=5)
score: 0.9229041916167665
C: [3.79269019 3.79269019 3.79269019 3.79269019]

*1:手元の環境だと計算に時間がかかりすぎて、いろいろなモデルを実験するのが難しかったので。。

自然言語処理100本ノック2020(Rev 2)の記録 Chapter 5

自然言語処理100本ノック2020(Rev 2)の記録(Python 3.11)

Chapter 5 係り受け解析

日本語Wikipediaの「人工知能」に関する記事からテキスト部分を抜き出したファイルがai.ja.zipに収録されている. この文章をCaboChaやKNP等のツールを利用して係り受け解析を行い,その結果をai.ja.txt.parsedというファイルに保存せよ. このファイルを読み込み,以下の問に対応するプログラムを実装せよ.

メモ

CaboChaはインストールがうまくいかず、最新版(v0.69)が2015年?らしいので、Ginzaでやってみることにする。

Ginzaは自然言語処理フレームワークにspaCyを使っているが、 Numpy v2.0.0だとspaCyが動かないようなので、こちらを見てNumpyのバージョンをpip install numpy==1.26.4で指定、 その後pip install -U ginza ja_ginzaでインストールした。

ginzaがコマンドラインで使用できるようになり、 ginza -f cabochaでCaboCha風の出力ができる。これを使って、 cat ai.ja.txt | ginza -f cabocha > ai.ja.txt.parsedで、係り受け解析後のファイルを作成した。

CaboChaのアウトプットは以下のような形式。

% cabocha -f1
太郎は花子が読んでいる本を次郎に渡した
* 0 5D 0/1 1.062087
太郎    名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
* 1 2D 0/1 1.821210
花子    名詞,固有名詞,人名,名,*,*,花子,ハナコ,ハナコ
が      助詞,格助詞,一般,*,*,*,が,ガ,ガ
* 2 3D 0/2 0.000000
読ん    動詞,自立,*,*,五段・マ行,連用タ接続,読む,ヨン,ヨン
で      助詞,接続助詞,*,*,*,*,で,デ,デ
いる    動詞,非自立,*,*,一段,基本形,いる,イル,イル
* 3 5D 0/1 0.000000
本      名詞,一般,*,*,*,*,本,ホン,ホン
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
* 4 5D 1/2 0.000000
次      名詞,一般,*,*,*,*,次,ツギ,ツギ
郎      名詞,一般,*,*,*,*,郎,ロウ,ロー
に      助詞,格助詞,一般,*,*,*,に,ニ,ニ
* 5 -1D 0/1 0.000000
渡し    動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ
た      助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
EOS

文節についての情報は、* [文節番号(文内)] [係り先の文節番号(ない場合は-1)]D [主辞の形態素番号(文節内)]/[機能語の形態素番号] [スコア]の出力形式。 第2文節「読んでいる」は、係り先が第3文節「本を」で、主辞は0番目の「読ん」、機能語は2番目の「いる」となる。

形態素の出力はMeCab形式。 [表層形]\t[素性]で、 素性は[品詞],[品詞細分類1],[属性1?],[属性2?],[活用型],[活用形],[基本形],[読み1?],[読み2?]の形式。 属性1?には、名詞の場合には「サ変可能」(開発する)とか、 「形状詞*1可能」(高速な)とかの変化? の他、 「人名」「地名」などの情報が記載される。属性2?には「姓」「国」など、詳細情報が記載される。

文ごとに、終わりにはEOSが出力される。

40. 係り受け解析結果の読み込み(形態素)

形態素を表すクラスMorphを実装せよ. このクラスは表層形(surface),基本形(base),品詞(pos),品詞細分類1(pos1)をメンバ変数に持つこととする. さらに,係り受け解析の結果(ai.ja.txt.parsed)を読み込み,各文をMorphオブジェクトのリストとして表現し,冒頭の説明文の形態素列を表示せよ.

メモ

全角カンマ(多分半角も)の原形が,で、 , 補助記号,読点,,,,,,,,,* O とエスケープせずに出力されるので、これだけ表層形を見て個別に入力する。

各文をMorphオブジェクトのリスト(sentence)として表現し、 文章(document)をそのリスト(sentence)のリストとして表現する。 第0文は見出し「人工知能」なので、第1文を「冒頭の説明文」とした。

指定されていないが、あとで使うので、属性1?(「サ変可能」など)をattributeとしてメンバ変数に追加している。

class Morph:
    def __init__(self, surface, base, pos, pos1, attribute):
        self.surface = surface
        self.base = base
        self.pos = pos
        self.pos1 = pos1
        self.attribute = attribute

    def __str__(self):
        return(f"{self.surface}\t{self.base},{self.pos},{self.pos1},{self.attribute}")

sentence = []
document = []
with open("ai.ja.txt.parsed", mode="r") as f:
    for line in f.readlines():
        line = line.strip()

        # empty line
        if line == "":
            pass
            
        # end of statement
        elif line == "EOS":
            document.append(sentence)
            sentence = []

        # beginning of bunsetu
        elif line[0] == "*":
            pass

        # morph
        else:
            surface, feature, *_  = line.split("\t")

            if surface in (",", ","):
                base = ","
                pos = "補助記号"
                pos1 = "読点"
                attribute = "*"
            else:
                pos, pos1, attribute, _, _, _, base, *_ = feature.split(",")

            sentence.append(Morph(surface, base, pos, pos1, attribute))

# output
for morph in document[1]:
    print(morph)
人工知能    人工知能,名詞,普通名詞,一般
(   (,補助記号,括弧開,*
じん  じん,名詞,普通名詞,一般
こうち こうち,名詞,普通名詞,形状詞可能
のう  のう,助詞,終助詞,*
、   、,補助記号,読点,*
、   、,補助記号,読点,*
AI  AI,名詞,普通名詞,一般
〈   〈,補助記号,括弧開,*
エーアイ    エーアイ,名詞,固有名詞,一般
〉   〉,補助記号,括弧閉,*
)   ),補助記号,括弧閉,*
と   と,助詞,格助詞,*
は   は,助詞,係助詞,*
、   、,補助記号,読点,*
「   「,補助記号,括弧開,*
『   『,補助記号,括弧開,*
計算  計算,名詞,普通名詞,サ変可能
(   (,補助記号,括弧開,*
)   ),補助記号,括弧閉,*
』   』,補助記号,括弧閉,*
と   と,助詞,格助詞,*
いう  いう,動詞,一般,*
概念  概念,名詞,普通名詞,一般
と   と,助詞,格助詞,*
『   『,補助記号,括弧開,*
コンピュータ  コンピュータ,名詞,普通名詞,一般
(   (,補助記号,括弧開,*
)   ),補助記号,括弧閉,*
』   』,補助記号,括弧閉,*
と   と,助詞,格助詞,*
いう  いう,動詞,一般,*
道具  道具,名詞,普通名詞,一般
を   を,助詞,格助詞,*
用い  用いる,動詞,一般,*
て   て,助詞,接続助詞,*
『   『,補助記号,括弧開,*
知能  知能,名詞,普通名詞,一般
』   』,補助記号,括弧閉,*
を   を,助詞,格助詞,*
研究  研究,名詞,普通名詞,サ変可能
する  する,動詞,非自立可能,*
計算機科学   計算機科学,名詞,普通名詞,一般
(   (,補助記号,括弧開,*
)   ),補助記号,括弧閉,*
の   の,助詞,格助詞,*
一   一,名詞,数詞,*
分野  分野,名詞,普通名詞,一般
」   」,補助記号,括弧閉,*
を   を,助詞,格助詞,*
指す  指す,動詞,一般,*
語   語,名詞,普通名詞,一般
。   。,補助記号,句点,*

41. 係り受け解析結果の読み込み(文節・係り受け)

40に加えて,文節を表すクラスChunkを実装せよ. このクラスは形態素(Morphオブジェクト)のリスト(morphs),係り先文節インデックス番号(dst),係り元文節インデックス番号のリスト(srcs)をメンバ変数に持つこととする. さらに,入力テキストの係り受け解析結果を読み込み,1文をChunkオブジェクトのリストとして表現し,冒頭の説明文の文節の文字列と係り先を表示せよ.本章の残りの問題では,ここで作ったプログラムを活用せよ.

メモ

係り先および係り元のリストの処理は、一旦配列(depends)に格納しておいて、EOSを読んだときにまとめて処理。

文節は、形態素を+で結合して出力する。

係り受け関係については、インデックス番号より直接Chunkオブジェクトを指した方が使いやすい気がしたので、 そのようなメンバ変数cdstcsrcsを追加。

指定されていないが、あとで使うので、 インデックス番号をidn、 主辞をhead、機能語をfuncとしてメンバ変数に追加している。

また、morphsの形態素列を順に出力するメソッド(show())を定義しておく。 elim=Trueで句読点などの記号(補助記号)を除くかどうかを切り替える。

class Chunk:
    def __init__(self, idn, morphs, head, func):
        self.idn = idn
        self.morphs = morphs
        
        self.dst = -1
        self.srcs = []
        self.cdst = None
        self.csrcs = []

        self.head = morphs[head]
        try:
            self.func = morphs[func]
        except(IndexError):
            self.func = None
            

    def __str__(self):
        return('+'.join(map(lambda m: m.surface, self.morphs)))

    def show(self, elim=True):
        buff = ""
        for m in self.morphs:
            if elim and m.pos == "補助記号":
                continue
            buff += m.surface
        return buff


depends = []
morphs = []
sentence = []
document = []
with open("ai.ja.txt.parsed", mode="r") as f:
    for line in f.readlines():
        line = line.strip()

        # empty line
        if line == "":
            pass
            
        # end of statement
        elif line == "EOS":
            sentence.append(Chunk(idx, morphs, head, func))

            for dp in depends:
                s, d = dp
                sentence[s].dst = d
                # not root
                if d >= 0:
                    sentence[s].cdst = sentence[d]
                    sentence[d].srcs.append(s)
                    sentence[d].csrcs.append(sentence[s])
            document.append(sentence)
            
            # clear
            sentence = []
            depends = []

        # beginning of bunsetu
        elif line[0] == "*":
            _, idx, dst, h_f, *_ = line.split(" ")
            idx = int(idx)
            # append previous chunck to sentence
            if idx != 0:
                sentence.append(Chunk(idx-1, morphs, head, func))

            dst = int(dst[:-1])
            depends.append((idx,dst))
            head, func = h_f.split("/")
            head = int(head)
            func = int(func)

            # clear
            morphs = []

        # morph
        else:
            surface, feature, *_  = line.split("\t")

            if surface in (",", ","):
                base = ","
                pos = "補助記号"
                pos1 = "読点"
                attribute = "*"
            else:
                pos, pos1, attribute, _, _, _, base, *_ = feature.split(",")

            morphs.append(Morph(surface, base, pos, pos1, attribute))


# output
for ch in document[1]:
        print(f"{ch.idn} {ch} dst={ch.dst}, srcs={ch.srcs}")
0 人工知能+(+じん+こうち+のう+、+、+AI+〈+エーアイ+〉+)+と+は+、+「+『+計算+(+)+』+と+いう dst=1, srcs=[]
1 概念+と dst=2, srcs=[0]
2 『+コンピュータ+(+)+』+と+いう dst=3, srcs=[1]
3 道具+を dst=4, srcs=[2]
4 用い+て dst=6, srcs=[3]
5 『+知能+』+を dst=6, srcs=[]
6 研究+する dst=7, srcs=[4, 5]
7 計算機科学+(+)+の+一+分野+」+を dst=8, srcs=[6]
8 指す dst=9, srcs=[7]
9 語+。 dst=-1, srcs=[8]

42. 係り元と係り先の文節の表示

係り元の文節と係り先の文節のテキストをタブ区切り形式ですべて抽出せよ. ただし,句読点などの記号は出力しないようにせよ.

メモ

係り元→係り先のタプルのリスト(pairs)として抽出。 一部のみ出力する。

import itertools

pairs = []
for sent in document:
    for ch in sent:
        if ch.cdst:
            pairs.append((ch, ch.cdst))

# output
for p in itertools.islice(pairs,50):
    s, d = p
    print(f"{s.show()}\t{d.show()}")
人工知能じんこうちのうAIエーアイとは計算という    概念と
概念と コンピュータという
コンピュータという   道具を
道具を 用いて
用いて 研究する
知能を 研究する
研究する    計算機科学の一分野を
計算機科学の一分野を  指す
指す  語
言語の 理解や
理解や 推論
推論  知的行動を
問題解決などの 知的行動を
知的行動を   代わって
人間に 代わって
代わって    行わせる
コンピューターに    行わせる
行わせる    技術
技術  される
または される
計算機コンピュータによる    情報処理システムの
知的な 情報処理システムの
情報処理システムの   設計や
設計や 実現に関する
実現に関する  研究分野とも
研究分野とも  される
日本大百科全書ニッポニカの   解説で
解説で 述べている
情報工学者通信工学者の 佐藤理史は
佐藤理史は   述べている
次の  ように
ように 述べている
人間の 知的能力を
知的能力を   実現する
コンピュータ上で    実現する
実現する    技術ソフトウェアコンピュータシステム
様々な 技術ソフトウェアコンピュータシステム
応用例は    自然言語処理機械翻訳かな漢字変換構文解析等
自然言語処理機械翻訳かな漢字変換構文解析等   ある
専門家の    推論判断を
推論判断を   模倣する
模倣する    エキスパートシステム
エキスパートシステム  画像データを
画像データを  解析して
解析して    検出抽出したり
特定の パターンを
パターンを   検出抽出したり
検出抽出したり する
する  画像認識等が
画像認識等が  ある

43. 名詞を含む文節が動詞を含む文節に係るものを抽出

名詞を含む文節が,動詞を含む文節に係るとき,これらをタブ区切り形式で抽出せよ. ただし,句読点などの記号は出力しないようにせよ.

メモ

特定の品詞がChunkのペアのどちらか(idxで指定)に含まれるかをチェックするinclude_posを定義。 partialで部分適用して、係り元と係り先のそれぞれにfilterをかけてpairsから抽出する。

一部のみ出力する。

from functools import partial

def include_pos(ch_pair, idx, pos):
    return pos in map(lambda m: m.pos, ch_pair[idx].morphs)

noun_in_src = partial(include_pos, idx=0, pos="名詞")
verb_in_dst = partial(include_pos, idx=1, pos="動詞")

n2v = filter(verb_in_dst, filter(noun_in_src, pairs))

# output
for p in itertools.islice(n2v, 50):
    s,d = p
    print(f"{s.show()}\t{d.show()}")
概念と コンピュータという
道具を 用いて
知能を 研究する
計算機科学の一分野を  指す
知的行動を   代わって
人間に 代わって
コンピューターに    行わせる
技術  される
設計や 実現に関する
研究分野とも  される
解説で 述べている
佐藤理史は   述べている
知的能力を   実現する
コンピュータ上で    実現する
自然言語処理機械翻訳かな漢字変換構文解析等   ある
推論判断を   模倣する
画像データを  解析して
解析して    検出抽出したり
パターンを   検出抽出したり
検出抽出したり する
画像認識等が  ある
1956年に  命名された
ダートマス会議で    命名された
ジョンマッカーシーにより    命名された
現在では    使われている
記号処理を   用いた
記述を する
主体と する
研究での    アプローチという
意味あいでも  使われている
思考ルーチンも 呼ばれることもある
カウンセラーを 模倣した
プログラム人工無脳が  出されるが
引き合いに   出されるが
計算機に    させようという
役割を させようという
エキスパートシステムと 呼ばれる
実現は なり
人間が 持つ
暗黙に 持つ
記述が なり
問題と なり
利用が 困難視されている
実現への    アプローチとしては
アプローチとしては   知られているが
アプローチも  知られているが
従来の 人工知能であるGoodOldFashionedAIとの
差は  ある
記号的明示性に ある
その後 集めた

44. 係り受け木の可視化

与えられた文の係り受け木を有向グラフとして可視化せよ. 可視化には,Graphviz等を用いるとよい.

メモ

Jupyterにgraphvizでpng出力する方法は公式のサンプルを参照。 graphviz.set_jupyter_format('png')すればよいみたい。

これまで第1文を対象にしてきたので、ここでは第2文を対象にした。

import graphviz
graphviz.set_jupyter_format('png')

sentence = document[2]
dot = graphviz.Digraph()
for ch in sentence:
    dot.node(str(ch.idn), ch.show(elim=False))
    if ch.cdst:
        dot.edge(str(ch.idn), str(ch.cdst.idn))

# output
dot

45. 動詞の格パターンの抽出

今回用いている文章をコーパスと見なし,日本語の述語が取りうる格を調査したい. 動詞を述語,動詞に係っている文節の助詞を格と考え,述語と格をタブ区切り形式で出力せよ. ただし,出力は以下の仕様を満たすようにせよ.
  • 動詞を含む文節において,最左の動詞の基本形を述語とする
  • 述語に係る助詞を格とする
  • 述語に係る助詞(文節)が複数あるときは,すべての助詞をスペース区切りで辞書順に並べる
「ジョン・マッカーシーはAIに関する最初の会議で人工知能という用語を作り出した。」という例文を考える. この文は「作り出す」という1つの動詞を含み,「作り出す」に係る文節は「ジョン・マッカーシーは」,「会議で」,「用語を」であると解析された場合は,次のような出力になるはずである.
作り出す    で は を
このプログラムの出力をファイルに保存し,以下の事項をUNIXコマンドを用いて確認せよ.
  • コーパス中で頻出する述語と格パターンの組み合わせ
  • 「行う」「なる」「与える」という動詞の格パターン(コーパス中で出現頻度の高い順に並べよ)

メモ

「…アプローチとしては、…知られているが…」のような文の場合、 係り元の文節は助詞「と」「て」「は」を含み、係り先の文節は動詞「知る」「いる」を含む。 動詞の場合は、最左の動詞なので「知る」が対象になる。 助詞の場合、文節内に複数ある場合にどうするか、上記のみからははっきりしない*2。 ここでは機能語として抽出されたもの「と」を対象とする。 係り元のない文節に動詞がある場合はカウントから除いた。

Chunkから最左の動詞(のMorph)を抽出する関数ext_verb(なければNone)と、 Chunkから機能語となっている助詞(のMorph)を抽出する関数ext_particle(なければNone)を定義。

UNIXコマンドでの抽出はChapter 02を参照。 「なる」の場合は「異なる」などが抽出されるので、単語の前のスペースを含めて検索した。

def ext_verb(chunk):
    for morph in chunk.morphs:
        if morph.pos == "動詞":
            return morph
    return None

def ext_particle(chunk):
    func = chunk.func
    if func and func.pos == "助詞":
        return func
    return None

cases = []
for sentence in document:
    for ch in sentence:
        verb = ext_verb(ch)
        if verb:
            particles = []
            for src in ch.csrcs:
                part = ext_particle(src)
                if part:
                    particles.append(part)
            if particles:
                particles = sorted(map(lambda m: m.base, particles))
                cases.append((verb.base, particles))

# output
with open("knock45.txt", mode="w") as f:
    for v, ps in cases:
        f.write(f"{v}\t{' '.join(ps)}\n")

n = 10

print("frequently appearing case patterns")
pattern = !sort knock45.txt | uniq -c | sort -k 1 -d -r
for p in itertools.islice(pattern, n):
    print(p)

print("'行う' case patterns")
pattern = !sort knock45.txt | uniq -c | sort -k 1 -d -r | grep 行う
for p in itertools.islice(pattern, n):
    print(p)

print("'なる' case patterns")
pattern = !sort knock45.txt | uniq -c | sort -k 1 -d -r | grep " なる"
for p in itertools.islice(pattern, n):
    print(p)

print("'与える' case patterns")
pattern = !sort knock45.txt | uniq -c | sort -k 1 -d -r | grep 与える
for p in itertools.islice(pattern, n):
    print(p)
frequently appearing case patterns
     56 する  を
     22 する  が
     19 する  に
     16 する  と
     13 する  は
     12 する  は を
     11 する  が に
     10 する  で を
      9 する  に を
      7 行う  を
'行う' case patterns
      7 行う  を
      3 行う  に を
      2 行う  は を
      2 行う  で を
      1 行う  の は
      1 行う  に まで を
      1 行う  に は を
      1 行う  に
      1 行う  で は を
      1 行う  て に
'なる' case patterns
      4 なる  が と
      3 なる  は
      3 なる  に は
      3 なる  に
      3 なる  と
      2 なる  で
      1 なる  は も
      1 なる  と に も
      1 なる  と に は
      1 なる  で に
'与える' case patterns
      1 与える に は を
      1 与える が など
      1 与える が

46. 動詞の格フレーム情報の抽出

45のプログラムを改変し,述語と格パターンに続けて項(述語に係っている文節そのもの)をタブ区切り形式で出力せよ. 45の仕様に加えて,以下の仕様を満たすようにせよ.
  • 項は述語に係っている文節の単語列とする(末尾の助詞を取り除く必要はない)
  • 述語に係る文節が複数あるときは,助詞と同一の基準・順序でスペース区切りで並べる
「ジョン・マッカーシーはAIに関する最初の会議で人工知能という用語を作り出した。」という例文を考える. この文は「作り出す」という1つの動詞を含み,「作り出す」に係る文節は「ジョン・マッカーシーは」,「会議で」,「用語を」であると解析された場合は,次のような出力になるはずである.
作り出す    で は を   会議で ジョンマッカーシーは 用語を

メモ

出力する文節chunksを追加。

cases = []
for sentence in document:
    for ch in sentence:
        verb = ext_verb(ch)
        if verb:
            particles = []
            chunks = []
            for src in ch.csrcs:
                part = ext_particle(src)
                if part:
                    particles.append(part)
                    chunks.append(src.show(elim=False))
            if particles:
                particles = sorted(map(lambda m: m.base, particles))
                chunks = sorted(chunks)
                cases.append((verb.base, particles, chunks))

# output
for v, ps, cs in itertools.islice(cases, 50):
    print(f"{v}\t{' '.join(ps)}\t{' '.join(cs)}")
いう  と   概念と
用いる を   道具を
する  て を 『知能』を 用いて
指す  を   計算機科学()の一分野」を
代わる に を 人間に 知的行動を
行う  て に コンピューターに 代わって
関する や   設計や
する  と は または、 研究分野」とも
述べる で は 佐藤理史は 解説で、
する  で を コンピュータ上で 知的能力を
する  を   推論・判断を
する  を   画像データを
する  を   パターンを
ある  が   画像認識等が
する  で に に   1956年に ジョン・マッカーシーにより ダートマス会議で
用いる を   記号処理を
する  と を 主体と 記述を
いう  で   研究での
使う  で で 意味あいでも 現在では、
呼ぶ  も   思考ルーチンも
する  を   カウンセラーを
出す  が に プログラム(人工無脳)が 引き合いに
する  に を 役割を 計算機に
呼ぶ  と   「エキスパートシステム」と
持つ  が に 人間が 暗黙に
なる  が と は   問題と 実現は、 記述が
する  が   利用が
する  へ   実現への
知る  と も アプローチとしては、 アプローチも
ある  の   従来の
ある  に は 差は 記号的明示性に
集める が を 「サポートベクターマシン」が 注目を
行う  に を 元に 学習を
ある  も   手法も
ある  に   宇宙において、
する  を   知性を
ある  と は ことは 形質である(レイ・カーツワイル)」という
よる  と の ビッグデータの 登場と
超える を   流行を
する  て に 社会に 超えて
行く  に   登場により、
かける に   2017年に
する  て を かけて、 ディープラーニングを
破る  が も AIが プレイヤーも
する  が で に   「MicrosoftSuphx(SuperPhoenix)」が 十段に 麻雀では
なる  と   最先端技術と
呼ぶ  と は 人工知能は 機械学習と
ある  が   ものが
繰り返す    を   学習を
する  と は を   ことを 基本と 計算知能(CI)は

47. 機能動詞構文のマイニング

動詞のヲ格にサ変接続名詞が入っている場合のみに着目したい.46のプログラムを以下の仕様を満たすように改変せよ.
  • 「サ変接続名詞+を(助詞)」で構成される文節が動詞に係る場合のみを対象とする
  • 述語は「サ変接続名詞+を+動詞の基本形」とし,文節中に複数の動詞があるときは,最左の動詞を用いる
  • 述語に係る助詞(文節)が複数あるときは,すべての助詞をスペース区切りで辞書順に並べる
  • 述語に係る文節が複数ある場合は,すべての項をスペース区切りで並べる(助詞の並び順と揃えよ)
例えば「また、自らの経験を元に学習を行う強化学習という手法もある。」という文から,以下の出力が得られるはずである.
学習を行う   に を 元に 経験を

メモ

上記文例では、「経験を」→「元に」、「元に」→「学習を」になって、出力は学習を行う に 元にとなるのでは? (「経験を」は「学習を」にも「行う」にも直接は係らないのでは?) 実際、GiNZAの出力(ai.ja.txt.parsed)を見るとそのようになっている。CaboChaの解析精度の問題?

ここでは、「主辞が『サ変接続(サ変可能)名詞』で機能語が『を』である文節」を係り先とする文節を、「述語に係る文節」として抽出するようにする。 Chunkから「サ変接続(サ変可能)名詞+を」を抽出して(Morphのタプルで)返す関数ext_sahen_wo(なければNone)を用意する。

動詞を含む文節を見つけたあと、 その係り元で「サ変可能+を」を探して、 さらにその係り元をその後係り元を検索するようにしている。

def ext_sahen_wo(chunk):
    head = chunk.head
    func = chunk.func
    if head.attribute == "サ変可能" and func and func.base == "を":
        return head, func
    return None

cases = []
for sentence in document:
    for ch in sentence:
        verb = ext_verb(ch)
        if verb:
            for src1 in ch.csrcs:
                sahen_wo = ext_sahen_wo(src1)
                if sahen_wo:
                    particles = []
                    chunks = []
                    for src2 in src1.csrcs:
                        part = ext_particle(src2)
                        if part:
                            particles.append(part)
                            chunks.append(src2.show(elim=False))
                    if particles:
                        comp = ''.join(map(lambda m: m.base, (*sahen_wo, verb)))
                        particles = sorted(map(lambda m: m.base, particles))
                        chunks = sorted(chunks)
                        cases.append((comp, particles, chunks))

# output
for v, ps, cs in itertools.islice(cases, 50):
    print(f"{v}\t{' '.join(ps)}\t{' '.join(cs)}")
行動を代わる  など  問題解決などの
判断をする   の   専門家の
記述をする   の   知能の
流行を超える  の   一過性の
学習を繰り返す や   開発や
生成を行う   と   CreativeAIという
開発を行う   の   機械式計算機の
テストをする  に   知的ふるまいに関する
研究を進める  の   第五世代コンピュータの
命令をする   の   Prologの
研究をする   に   制御についての
注目を集める  の   世間の
チューニングをする   の   ルールの
成功を受ける  の   試みの
制御を用いる  の   同様の
制御をする   の   家電製品の
進歩を担う   の   科学技術の
改善を果たす  から  従来手法からの
学習をする   の   不要の
注目を集める  の   識者の
普及を受ける  と   発明と
実験をする   の   新技術の
弾圧を併せ持つ の   人権の
差別を認める  で   融資での
自動化を試みる で   分野での
展開を変える  の   部隊の
バランスを決める    の   大国間の
判断を介す   の   人間の
禁止を求める  の   自動操縦型武器の
利用をめぐる  の   人工知能の
記録をする   の   米軍の
試験を行う   の   世界最大規模の
共同研究をする と の AIの 教育機関と
解散をする   の   委員会の
実現をする   の   Godheadの
崇拝を通す   と   理解と
話をする    の   異界の

48. 名詞から根へのパスの抽出

文中のすべての名詞を含む文節に対し,その文節から構文木の根に至るパスを抽出せよ. ただし,構文木上のパスは以下の仕様を満たすものとする.
  • 各文節は(表層形の)形態素列で表現する
  • パスの開始文節から終了文節に至るまで,各文節の表現を->で連結する
「ジョン・マッカーシーはAIに関する最初の会議で人工知能という用語を作り出した。」という例文を考える. CaboChaを係り受け解析に用いた場合,次のような出力が得られると思われる.
ジョンマッカーシーは -> 作り出した
AIに関する -> 最初の -> 会議で -> 作り出した
最初の -> 会議で -> 作り出した
会議で -> 作り出した
人工知能という -> 用語を -> 作り出した
用語を -> 作り出した
KNPを係り受け解析に用いた場合,次のような出力が得られると思われる.
ジョンマッカーシーは -> 作り出した
AIに -> 関する -> 会議で -> 作り出した
会議で -> 作り出した
人工知能と -> いう -> 用語を -> 作り出した
用語を -> 作り出した

メモ

Chunkを構文木(係り受け木?)の根まで順に返すジェネレータchainを定義。 各分節について名詞を含むかどうかをチェック(noun_check)して、 名詞を含む場合に根まで出力すればOK。

第2文を対象とした。

def chain(chunk):
    yield chunk
    if chunk.cdst:
        yield from chain(chunk.cdst)

for ch in document[2]:
    if "名詞" in map(lambda m:m.pos, ch.morphs):
        print(' -> '.join(map(lambda c:c.show(elim=False), chain(ch))))
「言語の -> 理解や -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 -> される。
理解や -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 -> される。
推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 -> される。
問題解決などの -> 知的行動を -> 代わって -> 行わせる -> 技術」、 -> される。
知的行動を -> 代わって -> 行わせる -> 技術」、 -> される。
人間に -> 代わって -> 行わせる -> 技術」、 -> される。
コンピューターに -> 行わせる -> 技術」、 -> される。
技術」、 -> される。
「計算機(コンピュータ)による -> 情報処理システムの -> 設計や -> 実現に関する -> 研究分野」とも -> される。
情報処理システムの -> 設計や -> 実現に関する -> 研究分野」とも -> される。
設計や -> 実現に関する -> 研究分野」とも -> される。
実現に関する -> 研究分野」とも -> される。
研究分野」とも -> される。

49. 名詞間の係り受けパスの抽出

文中のすべての名詞句のペアを結ぶ最短係り受けパスを抽出せよ. ただし,名詞句ペアの文節番号が$ i $と$ j $($ i < j $)のとき,係り受けパスは以下の仕様を満たすものとする.
  • 問題48と同様に,パスは開始文節から終了文節に至るまでの各文節の表現(表層形の形態素列)を->で連結して表現する
  • 文節$ i $と$ j $に含まれる名詞句はそれぞれ,XとYに置換する
また,係り受けパスの形状は,以下の2通りが考えられる.
  • 文節$ i $から構文木の根に至る経路上に文節$ j $が存在する場合: 文節$ i $から文節$ j $のパスを表示
  • 上記以外で,文節$ i $と文節$ j $から構文木の根に至る経路上で共通の文節$ k $で交わる場合: 文節$ i $から文節$ k $に至る直前のパスと文節$ j $から文節$ k $に至る直前までのパス,文節$ k $の内容を|で連結して表示
「ジョン・マッカーシーはAIに関する最初の会議で人工知能という用語を作り出した。」という例文を考える. CaboChaを係り受け解析に用いた場合,次のような出力が得られると思われる.
Xは | Yに関する -> 最初の -> 会議で | 作り出した
Xは | Yの -> 会議で | 作り出した
Xは | Yで | 作り出した
Xは | Yという -> 用語を | 作り出した
Xは | Yを | 作り出した
Xに関する -> Yの
Xに関する -> 最初の -> Yで
Xに関する -> 最初の -> 会議で | Yという -> 用語を | 作り出した
Xに関する -> 最初の -> 会議で | Yを | 作り出した
Xの -> Yで
Xの -> 会議で | Yという -> 用語を | 作り出した
Xの -> 会議で | Yを | 作り出した
Xで | Yという -> 用語を | 作り出した
Xで | Yを | 作り出した
Xという -> Yを
KNPを係り受け解析に用いた場合,次のような出力が得られると思われる.
Xは | Yに -> 関する -> 会議で | 作り出した。
Xは | Yで | 作り出した。
Xは | Yと -> いう -> 用語を | 作り出した。
Xは | Yを | 作り出した。
Xに -> 関する -> Yで
Xに -> 関する -> 会議で | Yと -> いう -> 用語を | 作り出した。
Xに -> 関する -> 会議で | Yを | 作り出した。
Xで | Yと -> いう -> 用語を | 作り出した。
Xで | Yを | 作り出した。
Xと -> いう -> Yを

メモ

名詞句」として、主辞が名詞である文節を抽出する。 名詞が複数ある場合、主辞の名詞をX,Yに置換する。 (「ジョン・マッカーシーは」という文節など、 「ジョン(名詞)」「・(補助記号)」「マッカーシー(名詞:主辞)」「は(助詞)」と複数の名詞を含む場合に対応するため。)

主辞が名詞であるかをチェックし、 名詞である場合には置換した文節の文字列を、 名詞でない場合にはNoneを返す関数subst_nounを定義。

第2文を対象とした。 可視化した係り受け木とも整合している。

def subst_noun(chunk, symb):
    if chunk.head.pos == "名詞":
        buff = ""
        for morph in chunk.morphs:
            if morph == chunk.head:
                buff += symb
            else:
                buff += morph.surface
        return buff
    else:
        return None


for ich, jch in itertools.combinations(document[2], 2):
    # check whether chunk-head is noun or not, and substitute chunk-head to X/Y
    x_phrase = subst_noun(ich, "X")
    y_phrase = subst_noun(jch, "Y")
    
    if x_phrase and y_phrase:

        # case where chunk-j is on the path from chunk-i to root of the syntax tree 
        if jch in chain(ich):
            out = [x_phrase] # substituted
            # iteration start from chunk next to x_phrase
            for ch in chain(ich.cdst):
                if ch == jch:
                    break
                else:
                    out.append(ch.show(elim=False))
            out.append(y_phrase) # substituted

            # output
            print(' -> '.join(out))
            
        # case where chunk-j is NOT on the path from chunk-i to root of the syntax tree 
        else:
            outx = [x_phrase] # substituted
            # iteration start from chunk next to x_phrase
            for ch in chain(ich.cdst):
                if ch not in chain(jch):
                    outx.append(ch.show(elim=False))
                else:
                    break

            outy = [y_phrase] # substituted
            outc = ""
            # iteration start from chunk next to y_phrase
            for ch in chain(jch.cdst):
                if ch not in chain(ich):
                    outy.append(ch.show(elim=False))
                else:
                    outc = ch.show(elim=False) # common chunk
                    break

            # output
            print(
                ' -> '.join(outx) + ' | ' +
                ' -> '.join(outy) + ' | ' +
                outc)
「Xの -> Yや
「Xの -> 理解や -> Y、
「Xの -> 理解や -> 推論、 | Yなどの | 知的行動を
「Xの -> 理解や -> 推論、 -> 知的Yを
「Xの -> 理解や -> 推論、 -> 知的行動を | Yに | 代わって
「Xの -> 理解や -> 推論、 -> 知的行動を -> 代わって | Yに | 行わせる
「Xの -> 理解や -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> Y」、
「Xの -> 理解や -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | 「Y(コンピュータ)による -> 情報処理システムの -> 設計や -> 実現に関する -> 研究分野」とも | される。
「Xの -> 理解や -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | 情報処理Yの -> 設計や -> 実現に関する -> 研究分野」とも | される。
「Xの -> 理解や -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | Yや -> 実現に関する -> 研究分野」とも | される。
「Xの -> 理解や -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | Yに関する -> 研究分野」とも | される。
「Xの -> 理解や -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | 研究Y」とも | される。
Xや -> Y、
Xや -> 推論、 | Yなどの | 知的行動を
Xや -> 推論、 -> 知的Yを
Xや -> 推論、 -> 知的行動を | Yに | 代わって
Xや -> 推論、 -> 知的行動を -> 代わって | Yに | 行わせる
Xや -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> Y」、
Xや -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | 「Y(コンピュータ)による -> 情報処理システムの -> 設計や -> 実現に関する -> 研究分野」とも | される。
Xや -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | 情報処理Yの -> 設計や -> 実現に関する -> 研究分野」とも | される。
Xや -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | Yや -> 実現に関する -> 研究分野」とも | される。
Xや -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | Yに関する -> 研究分野」とも | される。
Xや -> 推論、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | 研究Y」とも | される。
X、 | Yなどの | 知的行動を
X、 -> 知的Yを
X、 -> 知的行動を | Yに | 代わって
X、 -> 知的行動を -> 代わって | Yに | 行わせる
X、 -> 知的行動を -> 代わって -> 行わせる -> Y」、
X、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | 「Y(コンピュータ)による -> 情報処理システムの -> 設計や -> 実現に関する -> 研究分野」とも | される。
X、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | 情報処理Yの -> 設計や -> 実現に関する -> 研究分野」とも | される。
X、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | Yや -> 実現に関する -> 研究分野」とも | される。
X、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | Yに関する -> 研究分野」とも | される。
X、 -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | 研究Y」とも | される。
Xなどの -> 知的Yを
Xなどの -> 知的行動を | Yに | 代わって
Xなどの -> 知的行動を -> 代わって | Yに | 行わせる
Xなどの -> 知的行動を -> 代わって -> 行わせる -> Y」、
Xなどの -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | 「Y(コンピュータ)による -> 情報処理システムの -> 設計や -> 実現に関する -> 研究分野」とも | される。
Xなどの -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | 情報処理Yの -> 設計や -> 実現に関する -> 研究分野」とも | される。
Xなどの -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | Yや -> 実現に関する -> 研究分野」とも | される。
Xなどの -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | Yに関する -> 研究分野」とも | される。
Xなどの -> 知的行動を -> 代わって -> 行わせる -> 技術」、 | 研究Y」とも | される。
知的Xを | Yに | 代わって
知的Xを -> 代わって | Yに | 行わせる
知的Xを -> 代わって -> 行わせる -> Y」、
知的Xを -> 代わって -> 行わせる -> 技術」、 | 「Y(コンピュータ)による -> 情報処理システムの -> 設計や -> 実現に関する -> 研究分野」とも | される。
知的Xを -> 代わって -> 行わせる -> 技術」、 | 情報処理Yの -> 設計や -> 実現に関する -> 研究分野」とも | される。
知的Xを -> 代わって -> 行わせる -> 技術」、 | Yや -> 実現に関する -> 研究分野」とも | される。
知的Xを -> 代わって -> 行わせる -> 技術」、 | Yに関する -> 研究分野」とも | される。
知的Xを -> 代わって -> 行わせる -> 技術」、 | 研究Y」とも | される。
Xに -> 代わって | Yに | 行わせる
Xに -> 代わって -> 行わせる -> Y」、
Xに -> 代わって -> 行わせる -> 技術」、 | 「Y(コンピュータ)による -> 情報処理システムの -> 設計や -> 実現に関する -> 研究分野」とも | される。
Xに -> 代わって -> 行わせる -> 技術」、 | 情報処理Yの -> 設計や -> 実現に関する -> 研究分野」とも | される。
Xに -> 代わって -> 行わせる -> 技術」、 | Yや -> 実現に関する -> 研究分野」とも | される。
Xに -> 代わって -> 行わせる -> 技術」、 | Yに関する -> 研究分野」とも | される。
Xに -> 代わって -> 行わせる -> 技術」、 | 研究Y」とも | される。
Xに -> 行わせる -> Y」、
Xに -> 行わせる -> 技術」、 | 「Y(コンピュータ)による -> 情報処理システムの -> 設計や -> 実現に関する -> 研究分野」とも | される。
Xに -> 行わせる -> 技術」、 | 情報処理Yの -> 設計や -> 実現に関する -> 研究分野」とも | される。
Xに -> 行わせる -> 技術」、 | Yや -> 実現に関する -> 研究分野」とも | される。
Xに -> 行わせる -> 技術」、 | Yに関する -> 研究分野」とも | される。
Xに -> 行わせる -> 技術」、 | 研究Y」とも | される。
X」、 | 「Y(コンピュータ)による -> 情報処理システムの -> 設計や -> 実現に関する -> 研究分野」とも | される。
X」、 | 情報処理Yの -> 設計や -> 実現に関する -> 研究分野」とも | される。
X」、 | Yや -> 実現に関する -> 研究分野」とも | される。
X」、 | Yに関する -> 研究分野」とも | される。
X」、 | 研究Y」とも | される。
「X(コンピュータ)による -> 情報処理Yの
「X(コンピュータ)による -> 情報処理システムの -> Yや
「X(コンピュータ)による -> 情報処理システムの -> 設計や -> Yに関する
「X(コンピュータ)による -> 情報処理システムの -> 設計や -> 実現に関する -> 研究Y」とも
情報処理Xの -> Yや
情報処理Xの -> 設計や -> Yに関する
情報処理Xの -> 設計や -> 実現に関する -> 研究Y」とも
Xや -> Yに関する
Xや -> 実現に関する -> 研究Y」とも
Xに関する -> 研究Y」とも

*1:こちらによれば、UniDicで導入された「形容動詞の語幹部分に相当する品詞」らしい

*2:NLP業界では言うまでもないことなのかも知れませんが。。。

自然言語処理100本ノック2020(Rev 2)の記録 Chapter 4

自然言語処理100本ノック2020(Rev 2)の記録(Python 3.11)

Chapter 4 形態素解析

夏目漱石の小説『吾輩は猫である』の文章(neko.txt)をMeCabを使って形態素解析し,その結果をneko.txt.mecabというファイルに保存せよ.このファイルを用いて,以下の問に対応するプログラムを実装せよ. なお,問題37, 38, 39はmatplotlibもしくはGnuplotを用いるとよい.

メモ

mecab-python3unidic-liteをpipでインストール。

import MeCab
import unidic_lite

mecab = MeCab.Tagger()
with open('neko.txt') as fi, open('neko.txt.mecab', mode='w') as fo:
    fo.write(mecab.parse(fi.read()))

# output
!head -n 20 neko.txt neko.txt.mecab
==> neko.txt <==
一

 吾輩は猫である。
名前はまだ無い。

 どこで生れたかとんと見当がつかぬ。
何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。
しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。
この書生というのは時々我々を捕えて煮て食うという話である。
しかしその当時は何という考もなかったから別段恐しいとも思わなかった。
ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。
掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。
この時妙なものだと思った感じが今でも残っている。
第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。
その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。
のみならず顔の真中があまりに突起している。
そうしてその穴の中から時々ぷうぷうと煙を吹く。
どうも咽せぽくて実に弱った。
これが人間の飲む煙草というものである事はようやくこの頃知った。

==> neko.txt.mecab <==
一   イチ  イチ  一   名詞-数詞           2
                空白          
吾輩  ワガハイ    ワガハイ    我が輩 代名詞         0
は   ワ   ハ   は   助詞-係助詞          
猫   ネコ  ネコ  猫   名詞-普通名詞-一般          1
で   デ   ダ   だ   助動詞 助動詞-ダ   連用形-一般  
ある  アル  アル  有る  動詞-非自立可能    五段-ラ行   終止形-一般  1
。           。   補助記号-句点         
名前  ナマエ ナマエ 名前  名詞-普通名詞-一般          0
は   ワ   ハ   は   助詞-係助詞          
まだ  マダ  マダ  未だ  副詞          1
無い  ナイ  ナイ  無い  形容詞-非自立可能   形容詞 終止形-一般  1
。           。   補助記号-句点         
                空白          
どこ  ドコ  ドコ  何処  代名詞         1
で   デ   デ   で   助詞-格助詞          
生れ  ウマレ ウマレル    生まれる    動詞-一般   下一段-ラ行  連用形-一般  0
た   タ   タ   た   助動詞 助動詞-タ   終止形-一般  
か   カ   カ   か   助詞-終助詞          
と   ト   ト   と   助詞-格助詞          

30. 形態素解析結果の読み込み

形態素解析結果(neko.txt.mecab)を読み込むプログラムを実装せよ.ただし,各形態素は表層形(surface),基本形(base),品詞(pos),品詞細分類1(pos1)をキーとするマッピング型に格納し,1文を形態素(マッピング型)のリストとして表現せよ.第4章の残りの問題では,ここで作ったプログラムを活用せよ.

メモ

MeCaBの出力結果の読み方など、ipadicを使った場合の出力のようで(?)、上記の出力形式について記載したものが見つけられない。。((-Odumpオプションだと種類が多すぎて何だし、-Ochasenオプションはエラーが出て動かず、--node-formatオプションは読み込まれなかった)) 仕方がないので出力から次のようなものと推測する。

表層形\t表層形の読み\t基本形の読み\t基本形\t品詞(ハイフン区切りで細分化)\t活用型\t活用形\t(何かの数値)

この前提で、上記の”品詞”の先頭をpos、その次をpos1として読み込む(なければNone)。

最後の行はEOS\nなので、これは読み飛ばす。

from pprint import pprint
from itertools import islice

with open("neko.txt.mecab") as f:
    lines = f.readlines()

morphs = []
for line in lines:
    if line == "EOS\n":
        break
    surface, _, _, base, p, *_ = line.split("\t")
    p_iter = iter(p.split("-"))
    pos = next(p_iter, None)
    pos1 = next(p_iter, None)
    
    morphs.append({
        "surface" : surface,
        "base" : base,
        "pos" : pos,
        "pos1" : pos1,
    })

# output
for morph in islice(morphs, 20):
    pprint(morph)
{'base': '一', 'pos': '名詞', 'pos1': '数詞', 'surface': '一'}
{'base': '\u3000', 'pos': '空白', 'pos1': None, 'surface': '\u3000'}
{'base': '我が輩', 'pos': '代名詞', 'pos1': None, 'surface': '吾輩'}
{'base': 'は', 'pos': '助詞', 'pos1': '係助詞', 'surface': 'は'}
{'base': '猫', 'pos': '名詞', 'pos1': '普通名詞', 'surface': '猫'}
{'base': 'だ', 'pos': '助動詞', 'pos1': None, 'surface': 'で'}
{'base': '有る', 'pos': '動詞', 'pos1': '非自立可能', 'surface': 'ある'}
{'base': '。', 'pos': '補助記号', 'pos1': '句点', 'surface': '。'}
{'base': '名前', 'pos': '名詞', 'pos1': '普通名詞', 'surface': '名前'}
{'base': 'は', 'pos': '助詞', 'pos1': '係助詞', 'surface': 'は'}
{'base': '未だ', 'pos': '副詞', 'pos1': None, 'surface': 'まだ'}
{'base': '無い', 'pos': '形容詞', 'pos1': '非自立可能', 'surface': '無い'}
{'base': '。', 'pos': '補助記号', 'pos1': '句点', 'surface': '。'}
{'base': '\u3000', 'pos': '空白', 'pos1': None, 'surface': '\u3000'}
{'base': '何処', 'pos': '代名詞', 'pos1': None, 'surface': 'どこ'}
{'base': 'で', 'pos': '助詞', 'pos1': '格助詞', 'surface': 'で'}
{'base': '生まれる', 'pos': '動詞', 'pos1': '一般', 'surface': '生れ'}
{'base': 'た', 'pos': '助動詞', 'pos1': None, 'surface': 'た'}
{'base': 'か', 'pos': '助詞', 'pos1': '終助詞', 'surface': 'か'}
{'base': 'と', 'pos': '助詞', 'pos1': '格助詞', 'surface': 'と'}

31. 動詞

動詞の表層形をすべて抽出せよ.
set_surface = set()
for morph in filter(lambda m: m.get("pos") == "動詞", morphs):
    set_surface.add(morph["surface"])

# output
for surface in islice(set_surface, 20):
    print(surface)
わかっ
踏み出せ
有りゃ
しから
まぜ返し
解い
鳴らし
越せ
極める
拭い
なで
入れ
とら
擲つ
割っ
食う
詐る
恃み
聞き出し
くだけ

32. 動詞の基本形

動詞の基本形をすべて抽出せよ.
set_base = set()
for morph in filter(lambda m: m.get("pos") == "動詞", morphs):
    set_base.add(morph["base"])

# output
for base in islice(set_base, 20):
    print(base)
通り越す
ちょろまかす
仕出す
極める
食う
潜り込む
済む
結い巡らせる
積み重ねる
居た堪れる
零れる
浸かる
扱き上げる
立ち行く
占める
動ずる
押し通す
曇る
制する
産する

33. 「AのB」

2つの名詞が「の」で連結されている名詞句を抽出せよ.

メモ

itertoolspairwiseはiterableから2つずつ取り出すようなのでこれを使いたかったけど、 どうもペア限定らしい。。 というわけで、triplewiseを作って、それを使う。

「の」は助詞(格助詞)。 「次の日の朝の事」などの場合「日の朝」なども抽出されてしまうけど、 これを区別しようとすると係り受け解析などがいるのでは? ということで、機械的に抽出する。

def triplewise(iterable):
    # triplewise('ABCDEFG') → ABC BCD CDE DEF EFG
    iterator = iter(iterable)
    a = next(iterator, None)
    b = next(iterator, None)
    for c in iterator:
        yield a, b, c
        a = b
        b = c

phrases = []
for m1, m2, m3 in triplewise(morphs):
    if m1.get("pos") == "名詞" and m2.get("pos") == "助詞" and m3.get("pos") == "名詞" and m2.get("surface") == "の":
        phrases.append(m1.get("surface")+m2.get("surface")+m3.get("surface"))

# output
for phrase in islice(phrases, 20):
    print(phrase)
掌の上
書生の顔
ものの見
はずの顔
顔の真中
穴の中
書生の掌
掌の裏
藁の上
笹原の中
池の前
池の上
一樹の蔭
垣根の穴
隣家の三毛
時の通路
一刻の猶予
家の内
以外の人間
前の書生

34. 名詞の連接

名詞の連接(連続して出現する名詞)を最長一致で抽出せよ.

メモ

「連接」なので、1単語のみの場合は無視。

seq_nouns = []
buffer = []

for morph in morphs:
    if morph.get("pos") == "名詞":
        buffer.append(morph.get("surface"))
    else:
        if len(buffer) > 1:
            seq_nouns.append(''.join(buffer))
        buffer = []

# output
for seq_noun in islice(seq_nouns, 20):
    print(seq_noun)
見始
時妙
一毛
後猫
一度
上今
うち池
書生以外
間おさん
宿なし
まま奥
終日書斎
ぎりほとんど
時々忍び足
二三ページ
主人以外
朝主人
椽側
一間
神経胃弱

35. 単語の出現頻度

文章中に出現する単語とその出現頻度を求め,出現頻度の高い順に並べよ.

メモ

原形でカウントする。 単語なので、ここでは「記号」「補助記号」「空白」は除いた。 ここでは、後で上位10語でグラフ化することを考え、「助動詞」「助詞」「接頭辞」「接尾辞」も除いている。 (参考:UniDic品詞体系)

カウント対象かどうかをto_be_countedで判定、出現回数を辞書でカウントするcountを定義(で使う)。

ELIMINATE = ["記号", "補助記号", "空白", "助動詞", "助詞", "接頭辞", "接尾辞"]

def to_be_counted(morph):
    return morph.get("pos") not in ELIMINATE

def count(d, w):
    if w in d:
        d[w] += 1
    else:
        d[w] = 1


counter = dict()

for morph in filter(to_be_counted, morphs):
    count(counter, morph.get("base"))

counter = sorted(counter.items(), key=lambda itm:itm[1], reverse=True)

#output
for item in islice(counter,20):
    print(item)
('為る', 3923)
('有る', 2309)
('居る', 1773)
('言う', 1695)
('無い', 1693)
('事', 1269)
('物', 1101)
('成る', 1100)
('主人', 934)
('何', 850)
('其れ', 695)
('見る', 694)
('此の', 675)
('様', 661)
('来る', 622)
('其の', 619)
('良い', 540)
('思う', 516)
('此れ', 513)
('所', 506)

36. 頻度上位10語

出現頻度が高い10語とその出現頻度をグラフ(例えば棒グラフなど)で表示せよ.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib

n = 10
x = np.arange(n)
freq = [v for _, v in counter[:n]]
label = [k for k, _ in counter[:n]]

plt.title("「吾輩は猫である」における単語出現頻度")
plt.xlabel("単語")
plt.ylabel("出現頻度")

plt.bar(x, freq, tick_label=label, align="center")
plt.show()

37. 「猫」と共起頻度の高い上位10語

「猫」とよく共起する(共起頻度が高い)10語とその出現頻度をグラフ(例えば棒グラフなど)で表示せよ.

メモ

「共起」という場合、どの範囲で同時に出現するかについては場合によっていろいろある様子。 ここでは、次の2つで計算した。 「猫が猫と寝転ぶ」のような文だと「猫」が「猫」と共起することになるが、ここではこれは除いた。

  • cooc1:適当なサイズのウィンドウを決めて、その中で共起する数をカウントする
  • cooc2:句点「。」を区切りとして、各文で共起する数をカウントする*1
# co-occurance 1 (count in predetermined window)
window = 15 # one-side
nmorph = len(morphs)

cooc1 = dict()
for idx in filter(lambda i: morphs[i].get("base") == "猫", range(nmorph)):
    imin = max(0, idx-window)
    imax = min(nmorph, idx+window+1)
    for morph in filter(to_be_counted, morphs[imin:imax]):
        base = morph.get("base")
        if base != "猫":
            count(cooc1, base)

cooc1 = sorted(cooc1.items(), key=lambda itm:itm[1], reverse=True)

#output
n = 10
x = np.arange(n)
freq = [v for _, v in cooc1[:n]]
label = [k for k, _ in cooc1[:n]]

plt.title(f"「吾輩は猫である」における「猫」との共起頻度 (両側{window*2}語)")
plt.xlabel("単語")
plt.ylabel("出現頻度")

plt.bar(x, freq, tick_label=label, align="center")
plt.show()

# co-occurance 2 (count in each sentence)
cooc2 = dict()
buffer = []
for morph in morphs:
    buffer.append(morph)
    if morph.get('pos1') == "句点":
        if "猫" in [m.get("base") for m in buffer]:
            for m in filter(to_be_counted, buffer):
                base = m.get("base")
                if base != "猫":
                    count(cooc2, base)
        buffer = []

cooc2 = sorted(cooc2.items(), key=lambda itm:itm[1], reverse=True)

#output
n = 10
x = np.arange(n)
freq = [v for _, v in cooc2[:n]]
label = [k for k, _ in cooc2[:n]]

plt.title("「吾輩は猫である」における「猫」との共起頻度 (文ごと)")
plt.xlabel("単語")
plt.ylabel("出現頻度")

plt.bar(x, freq, tick_label=label, align="center")
plt.show()

38. ヒストグラム

単語の出現頻度のヒストグラムを描け.ただし,横軸は出現頻度を表し,1から単語の出現頻度の最大値までの線形目盛とする.縦軸はx軸で示される出現頻度となった単語の異なり数(種類数)である.

メモ

35counterが使える。 出現頻度1の単語が突出して多いので、拡大図を描いて、全体図をsubplotで追加。

freq = [v for _,v in counter]

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = fig.add_subplot(111)
nbin = 50

ax1.set(
    title="「吾輩は猫である」における単語の出現頻度分布",
    xlabel="出現頻度",
    ylabel="単語の種類",
    xlim=[0,4000],
    ylim=[0,100],
)

ax2.set(
    xlabel="出現頻度",
    ylabel="単語の種類",
    position=[0.5, 0.5, 0.35, 0.35],
    xlim=[0,4000],
)

ax1.hist(freq, bins=nbin)
ax2.hist(freq, bins=nbin)

plt.show()

39. Zipfの法則

単語の出現頻度順位を横軸,その出現頻度を縦軸として,両対数グラフをプロットせよ.

メモ

35counter(から作った38freq)が使える。

x = np.arange(len(freq))

plt.title("Zipfの法則")
plt.xlabel("順位")
plt.ylabel("出現頻度")
plt.xscale("log")
plt.yscale("log")

plt.scatter(x, freq)
plt.show()

おまけ

37でウィンドウサイズと、対象の語を変えた場合の違いを調べてみました。 ウィンドウサイズをいろいろ変えて両側30語(前15語、後15語の意味)にしたところで文ごとの集計と似た結果になったので、 大体30語程度の文が多いという感じかなと思っています。

ウィンドウサイズが広がると「為る」「有る」「無い」「居る」などが上がってきます。 これは文末までがターゲットに入るので、「…である。」などの語がカウントされやすくなる、という感じですかね。

「猫」との距離が2語と結構近いところに「我が輩」(「吾輩」の原形)があるようなので、 「吾輩のような猫から見ると人間というものは云々」とかそういう文が多いとか(3語以上離れているかも)?

「名前」との共起を見ると、「無い」より「有る」の方が多い感じです。 これも「である」など文末が要因なのでは?と思っています。 「貸す」も結構多いですね。

「我が輩」との共起では「主人」が出てくるので、 猫である「吾輩」から見た人間「主人」の様子が語られる、とかそんな構造が見えるような気もしますが、 どうでしょう?*2

from itertools import product

def cooc_window(morphs, window, target):
    cooc = dict()
    for idx in filter(lambda i: morphs[i].get("base") == target, range(nmorph)):
        imin = max(0, idx-window)
        imax = min(nmorph, idx+window+1)
        for morph in filter(to_be_counted, morphs[imin:imax]):
            base = morph.get("base")
            if base != target:
                count(cooc, base)
    return sorted(cooc.items(), key=lambda itm:itm[1], reverse=True)

n = 10
x = np.arange(n)

tcs = [("猫", "tab:blue"), ("名前", "tab:orange"), ("我が輩", "tab:green")] # (target and color)s
windows = [2, 5, 10]

for tc, window in product(tcs, windows):
    cooc = cooc_window(morphs, window, tc[0])
    freq = [v for _, v in cooc[:n]]
    label = [k for k, _ in cooc[:n]]

    plt.title(f"「吾輩は猫である」における「{tc[0]}」との共起頻度 (両側{window*2}語)")
    plt.xlabel("単語")
    plt.ylabel("出現頻度")
    plt.bar(x, freq, tick_label=label, align="center", color=tc[1])
    
    plt.show()

*1:冒頭の「一」のような句点の区切りがない場合、厳密にはカウントされませんが、大きな影響はないものとしてそのままカウントした

*2:読んだことはないので、聞きかじった程度でしか内容は知りません

自然言語処理100本ノック2020(Rev 2)の記録 Chapter 3

自然言語処理100本ノック2020(Rev 2)の記録(Python 3.11)

Chapter 3 正規表現

Wikipediaの記事を以下のフォーマットで書き出したファイルjawiki-country.json.gzがある.
  • 1行に1記事の情報がJSON形式で格納される
  • 各行には記事名が”title”キーに,記事本文が”text”キーの辞書オブジェクトに格納され,そのオブジェクトがJSON形式で書き出される
  • ファイル全体はgzipで圧縮される
以下の処理を行うプログラムを作成せよ.

メモ

jawiki-country.json.gzはjawiki-country.jsonに展開しておく。

20. JSONデータの読み込み

Wikipedia記事のJSONファイルを読み込み,「イギリス」に関する記事本文を表示せよ.問題21-29では,ここで抽出した記事本文に対して実行せよ.
import json
import re

with open('jawiki-country.json') as f:
    for line in f:
        article = json.loads(line)
        if article["title"] == "イギリス":
            ext = article["text"] 

print(ext)
{{redirect|UK}}
{{redirect|英国|春秋時代の諸侯国|英 (春秋)}}
{{Otheruses|ヨーロッパの国|長崎県・熊本県の郷土料理|いぎりす}}
{{基礎情報 国
|略名  =イギリス
|日本語国名 = グレートブリテン及び北アイルランド連合王国
|公式国名 = {{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>英語以外での正式国名:<br />
*{{lang|gd|An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath}}([[スコットランド・ゲール語]])
*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}([[ウェールズ語]])
*{{lang|ga|Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann}}([[アイルランド語]])
*{{lang|kw|An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh}}([[コーンウォール語]])
*{{lang|sco|Unitit Kinrick o Great Breetain an Northren Ireland}}([[スコットランド語]])
**{{lang|sco|Claught Kängrick o Docht Brätain an Norlin Airlann}}、{{lang|sco|Unitet Kängdom o Great Brittain an Norlin Airlann}}(アルスター・スコットランド語)</ref>
|国旗画像 = Flag of the United Kingdom.svg
|国章画像 = [[ファイル:Royal Coat of Arms of the United Kingdom.svg|85px|イギリスの国章]]
|国章リンク =([[イギリスの国章|国章]])
|標語 = {{lang|fr|[[Dieu et mon droit]]}}<br />([[フランス語]]:[[Dieu et mon droit|神と我が権利]])
|国歌 = [[女王陛下万歳|{{lang|en|God Save the Queen}}]]{{en icon}}<br />''神よ女王を護り賜え''<br />{{center|[[ファイル:United States Navy Band - God Save the Queen.ogg]]}}
|地図画像 = Europe-UK.svg
|位置画像 = United Kingdom (+overseas territories) in the World (+Antarctica claims).svg
|公用語 = [[英語]]
|首都 = [[ロンドン]](事実上)
|最大都市 = ロンドン
|元首等肩書 = [[イギリスの君主|女王]]
|元首等氏名 = [[エリザベス2世]]
|首相等肩書 = [[イギリスの首相|首相]]
|首相等氏名 = [[ボリス・ジョンソン]]
|他元首等肩書1 = [[貴族院 (イギリス)|貴族院議長]]
|他元首等氏名1 = [[:en:Norman Fowler, Baron Fowler|ノーマン・ファウラー]]
|他元首等肩書2 = [[庶民院 (イギリス)|庶民院議長]]
|他元首等氏名2 = {{仮リンク|リンゼイ・ホイル|en|Lindsay Hoyle}}
|他元首等肩書3 = [[連合王国最高裁判所|最高裁判所長官]]
|他元首等氏名3 = [[:en:Brenda Hale, Baroness Hale of Richmond|ブレンダ・ヘイル]]
|面積順位 = 76
|面積大きさ = 1 E11
|面積値 = 244,820
|水面積率 = 1.3%
|人口統計年 = 2018
|人口順位 = 22
|人口大きさ = 1 E7
|人口値 = 6643万5600<ref>{{Cite web|url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates|title=Population estimates - Office for National Statistics|accessdate=2019-06-26|date=2019-06-26}}</ref>
|人口密度値 = 271
|GDP統計年元 = 2012
|GDP値元 = 1兆5478億<ref name="imf-statistics-gdp">[http://www.imf.org/external/pubs/ft/weo/2012/02/weodata/weorept.aspx?pr.x=70&pr.y=13&sy=2010&ey=2012&scsm=1&ssd=1&sort=country&ds=.&br=1&c=112&s=NGDP%2CNGDPD%2CPPPGDP%2CPPPPC&grp=0&a=IMF>Data and Statistics>World Economic Outlook Databases>By Countrise>United Kingdom]</ref>
|GDP統計年MER = 2012
|GDP順位MER = 6
|GDP値MER = 2兆4337億<ref name="imf-statistics-gdp" />
|GDP統計年 = 2012
|GDP順位 = 6
|GDP値 = 2兆3162億<ref name="imf-statistics-gdp" />
|GDP/人 = 36,727<ref name="imf-statistics-gdp" />
|建国形態 = 建国
|確立形態1 = [[イングランド王国]]/[[スコットランド王国]]<br />(両国とも[[合同法 (1707年)|1707年合同法]]まで)
|確立年月日1 = 927年/843年
|確立形態2 = [[グレートブリテン王国]]成立<br />(1707年合同法)
|確立年月日2 = 1707年{{0}}5月{{0}}1日
|確立形態3 = [[グレートブリテン及びアイルランド連合王国]]成立<br />([[合同法 (1800年)|1800年合同法]])
|確立年月日3 = 1801年{{0}}1月{{0}}1日
|確立形態4 = 現在の国号「'''グレートブリテン及び北アイルランド連合王国'''」に変更
|確立年月日4 = 1927年{{0}}4月12日
|通貨 = [[スターリング・ポンド|UKポンド]] (£)
|通貨コード = GBP
|時間帯 = ±0
|夏時間 = +1
|ISO 3166-1 = GB / GBR
|ccTLD = [[.uk]] / [[.gb]]<ref>使用は.ukに比べ圧倒的少数。</ref>
|国際電話番号 = 44
|注記 = <references/>
}}

'''グレートブリテン及び北アイルランド連合王国'''(グレートブリテンおよびきたアイルランドれんごうおうこく、{{lang-en-short|United Kingdom of Great Britain and Northern Ireland}}: '''UK''')は、[[ヨーロッパ大陸]]の北西岸に位置し、[[グレートブリテン島]]・[[アイルランド島]]北東部・その他多くの島々から成る[[立憲君主制]][[国家]]。首都は[[ロンドン]]。[[日本語]]における[[通称]]の一例として'''イギリス'''、'''英国'''(えいこく)がある(→[[#国名]])。

'''[[イングランド]]'''、'''[[ウェールズ]]'''、'''[[スコットランド]]'''、'''[[北アイルランド]]'''という歴史的経緯に基づく4つの[[イギリスのカントリー|「カントリー」と呼ばれる「国」]]が、[[同君連合]]型の単一の[[主権国家体制|主権国家]]を形成する<ref name="page823">{{cite web |url=http://webarchive.nationalarchives.gov.uk/+/http://www.number10.gov.uk/Page823 |title=Countries within a country |publisher=Prime Minister's Office |accessdate=10 January 2003}}</ref>独特の統治体制を採るが、一般的に[[連邦]]国家とは区別される。

[[国際連合安全保障理事会常任理事国]]の一国(五大国)であり、[[G7]]・[[G20]]に参加する。GDPは世界10位以内に位置する巨大な市場を持ち、ヨーロッパにおける四つの大国「[[ビッグ4 (ヨーロッパ)|ビッグ4]]」の一国である。[[ウィーン体制]]が成立した[[1815年]]以来、世界で最も影響力のある国家・[[列強]]の一つに数えられる。また、[[民主主義]]、[[立憲君主制]]など近代国家の基本的な諸制度が発祥した国でもある。

イギリスの[[擬人化]]としては[[ジョン・ブル]]、[[ブリタニア (女神)|ブリタニア]]が知られる。

==国名==
正式名称は英語で「{{Lang|en|'''United Kingdom of Great Britain and Northern Ireland'''}}(ユナイテッド・キングダム・オヴ・グレイト・ブリテン・アンド・ノーザン・アイルランド)」であり、日本語では、「'''グレート・ブリテン及び北部アイルランド連合王国'''」とする場合(法文など)と「'''グレート・ブリテン及び北アイルランド連合王国'''」とする場合(条約文など)がある。

英語での略称は「{{Lang|en|'''United Kingdom'''}}」、「{{Lang|en|'''UK'''}}」。[[日本語]]における一般的な通称は「'''イギリス'''」もしくは「'''英国'''」であるが、稀に「{{Lang|en|United Kingdom}}」の[[直訳と意訳|直訳]]である「'''[[連合王国]]'''(れんごうおうこく)」が用いられることもある。現在の公用文では「英国」が使用されており、「イギリス」は口語で用いられることが多い<ref>[[日本放送協会|NHK]]で採用している他、原則として「英国」を用いるメディアでも「[[イギリス英語]]」のような形では使用する。</ref>。「連合王国」は2003年まで法文において用いられていた<ref>[http://warp.da.ndl.go.jp/info:ndljp/pid/1368617/www.meti.go.jp/policy/anpo/moto/topics/country/country.pdf 輸出貿易管理令等における国名表記の変更について]([[経済産業省]]) 国立国会図書館のアーカイブより''2019-2-5閲覧''</ref>。

「イギリス」は、[[ポルトガル語]]で[[イングランド]]を指す「{{Lang|pt|Inglez}}(イングレス)」が語源で、戦国時代にポルトガル人が来航した事に起源を持つ。原義にかかわらず連合王国全体を指して使われており、連合王国の構成体たる「イングランド」とは区別される。[[江戸時代]]には、[[オランダ語]]の「{{Lang|nl|Engelsch}}(エングルシュ)」を語源とする「'''エゲレス'''」という呼称も広く使用された<ref>[https://kotobank.jp/word/%E3%82%A8%E3%82%B2%E3%83%AC%E3%82%B9-444373 コトバンク「エゲレス」]</ref>。[[幕末]]から[[明治]]・[[大正]]期には「'''英吉利'''(えいぎりす)」や「大不列顛(だいふれつてん、大ブリテン)」と[[国名の漢字表記一覧|漢字で表記]]されることもあったが、前者が「英国」という略称の語源である。ただし「英国」は、狭義に連合王国全体でなくイングランド('''英格蘭''')のみを指す場合もある<ref>また、[[アメリカ合衆国]]に渡ることを「渡米」と言うように、イギリス、特にイングランドへ渡ることを「渡英」と言う([[二字熟語による往来表現の一覧]]を参照)。</ref>。

[[合同法 (1707年)|1707年合同法]]においては、[[イングランド王国]]および[[スコットランド王国]]を一王国に統合すると宣言する。同法において、新国家名称は「[[グレートブリテン王国]]」または「グレートブリテン連合王国」および「連合王国」とすると述べている<ref>{{cite web |url=http://www.scotshistoryonline.co.uk/union.html |title=Treaty of Union, 1706 |publisher=Scots History Online |accessdate=23 August 2011}}</ref><ref>{{cite book |url=http://books.google.com/?id=LYc1tSYonrQC&pg=PA165 |title=Constitutional & Administrative Law |page=165 |author=Barnett, Hilaire |author2=Jago, Robert |edition=8th |year=2011 |isbn=978-0-415-56301-7 |publisher=Routledge |location=Abingdon }}</ref>。しかしながら、「連合王国」という用語は18世紀における非公式の使用にのみ見られ、「長文式」でない単なる「グレート・ブリテン」であった1707年から1800年まで、同国はごくまれに正式名称である「グレート・ブリテン連合王国」と言及された<ref>See [[s:Act of Union 1707#Article 1 (name of the new kingdom)|Article One]] of the Act of Union 1707.</ref><ref name=name>"After the political union of England and Scotland in 1707, the nation's official name became 'Great Britain'", ''The American Pageant, Volume 1'', Cengage Learning (2012)</ref><ref name=name2>"From 1707 until 1801 ''Great Britain'' was the official designation of the kingdoms of England and Scotland". ''The Standard Reference Work:For the Home, School and Library, Volume 3'', Harold Melvin Stanford (1921)</ref><ref name=name3>"In 1707, on the union with Scotland, 'Great Britain' became the official name of the British Kingdom, and so continued until the union with Ireland in 1801". ''United States Congressional serial set, Issue 10;Issue 3265'' (1895)</ref><ref>{{cite web |url=http://www.historyworld.net/wrldhis/PlainTextHistories.asp?historyid=ab07 |title=History of Great Britain (from 1707) |authorlink=w:Bamber Gascoigne |author=Gascoigne, Bamber |publisher=History World |accessdate=18 July 2011}}</ref>。[[合同法 (1800年)|1800年合同法]]では、1801年にグレート・ブリテン王国と[[アイルランド王国]]が統合し、[[グレート・ブリテン及びアイルランド連合王国]]が成立した。現在の正式国名である「グレート・ブリテン及び北(部)アイルランド連合王国」は、[[北アイルランド]]のみが連合王国の一部としてとどまった1922年の[[アイルランド自由国]]独立および{{仮リンク|アイルランド分裂|en|Partition of Ireland}}後に採用された<ref>{{cite book |title=The Irish Civil War 1922–23 |author=Cottrell, P. |year=2008 |page=85 |isbn=1-84603-270-9}}</ref>。

イギリスは主権国家として国であるが、イングランド、[[スコットランド]]、[[ウェールズ]]、それほどの段階ではないが北アイルランドも、主権国家ではないが[[イギリスのカントリー|「国」(country)]]と呼ばれる<ref name="alphabeticalNI">{{citation |author1=S. Dunn |author2=H. Dawson|year=2000 |title=An Alphabetical Listing of Word, Name and Place in Northern Ireland and the Living Language of Conflict |publisher=Edwin Mellen Press |location=Lampeter |quote=One specific problem&nbsp;— in both general and particular senses&nbsp;— is to know what to call Northern Ireland itself:in the general sense, it is not a country, or a province, or a state&nbsp;— although some refer to it contemptuously as a statelet:the least controversial word appears to be jurisdiction, but this might change.}}</ref><ref>{{cite web |url=http://www.iso.org/iso/iso_3166-2_newsletter_ii-3_2011-12-13.pdf |title=Changes in the list of subdivision names and code elements |work=ISO 3166-2 |publisher=International Organization for Standardization |date=15 December 2011 |accessdate=28 May 2012}}</ref>。スコットランド、ウェールズ、北アイルランドは、権限の委譲による自治権を有する<ref>[http://books.google.com/?id=gPkDAQAAIAAJ Population Trends, Issues 75–82, p.38], 1994, UK Office of Population Censuses and Surveys</ref><ref name="citizenship">[http://books.google.com/?id=2u8rD6F-yg0C&pg=PA7 Life in the United Kingdom:a journey to citizenship, p. 7], United Kingdom Home Office, 2007, ISBN 978-0-11-341313-3.</ref>。イギリス首相のウェブサイトでは、連合王国の説明として「1国内の国々」という言葉が用いられていた<ref name="page823"/>。{{仮リンク|イギリスの12のNUTS1地域|en|NUTS of the United Kingdom}}統計のような複数の統計的概要において、スコットランド、ウェールズ、北アイルランドを「region」と言及している<ref>{{cite web |url=http://www.ons.gov.uk/ons/dcp171778_346117.xml |title=Statistical bulletin:Regional Labour Market Statistics |accessdate=5 March 2014 |archiveurl=https://web.archive.org/web/20141224045523/http://www.ons.gov.uk/ons/dcp171778_346117.xml |archivedate=2014年12月24日 |deadlinkdate=2018年3月 }}</ref><ref>{{cite web |url=http://www.gmb.org.uk/newsroom/fall-in-earnings-value-during-recession |title=13.4% Fall In Earnings Value During Recession |accessdate=5 March 2014}}</ref>。北アイルランドは「province」とも言及される<ref name="alphabeticalNI"/><ref name="placeApart">{{cite book |author=Murphy, Dervla |title=A Place Apart |year=1979 |publisher=Penguin |place=London |isbn=978-0-14-005030-1}}</ref>。北アイルランドに関しては、記述名の使用が「多くの場合、個人の政治的選好を明らかにする選択で議論の的になり得る」<ref>{{Cite book |last1=Whyte |first1=John |authorlink1=w:John Henry Whyte |last2=FitzGerald |first2=Garret|authorlink2=w:Garret FitzGerald|year=1991 |title=Interpreting Northern Ireland |location=Oxford |publisher=Clarendon Press |isbn=978-0-19-827380-6}}</ref>。

英語では「Britain」という言葉は、連合王国の同義語として頻繁に用いられる。一方、「Great Britain」という言葉は、連合王国全体の緩い同義語として用いられる場合もあるが<ref>{{cite web |url=http://www.merriam-webster.com/dictionary/great%20britain |title=Merriam-Webster Dictionary Online Definition of '&#39;Great Britain'&#39;|publisher=[[:en:Merriam Webster|Merriam Webster]] |date=31 August 2012 |accessdate=9 April 2013}}</ref><ref>[[:en:New Oxford American Dictionary|New Oxford American Dictionary]]:"Great Britain:England, Wales, and Scotland considered as a unit. The name is also often used loosely to refer to the United Kingdom."</ref>、本来はイングランド、スコットランドおよびウェールズを指すものであり、北アイルランドを含む(すなわち、イギリス全体を指す)場合には用いるべきでないとされる<ref>{{cite news |url=http://www.guardian.co.uk/styleguide/page/0,,184840,00.html |title=Guardian Unlimited Style Guide |publisher=Guardian News and Media Limited |accessdate=23 August 2011 |location=London |date=19 December 2008}}</ref><ref>{{cite news |url=http://news.bbc.co.uk/1/hi/programmes/radio_newsroom/1099593.stm#g|title=BBC style guide (Great Britain)|accessdate=23 August 2011 |work=BBC News|date=19 August 2002}}</ref><ref>{{cite web |url=http://www.direct.gov.uk/en/Governmentcitizensandrights/LivingintheUK/DG_10012517 |title=Key facts about the United Kingdom|archiveurl=http://webarchive.nationalarchives.gov.uk/20121015000000/http://www.direct.gov.uk/en/Governmentcitizensandrights/LivingintheUK/DG_10012517|archivedate=3 November 2012 |accessdate=8 March 2015 |work=Government, citizens and rights |publisher=HM Government}}</ref>。

"GB"及び"GBR"は、イギリスの[[国際標準化機構|標準]]国名コード ([[ISO 3166-2:GB|ISO 3166-2]]及び[[:en:ISO 3166-1 alpha-3|ISO 3166-1 alpha-3]]を参照) であり、その結果として国際機関がイギリスに言及する際に用いられることがある。さらに、イギリスのオリンピックチームは「Great Britain」もしくは「[[Team GB]]」の名称を用いる<ref>{{cite web |title=Great Britain |url=http://www.olympic.org/great-britain |publisher=International Olympic Committee |accessdate=10 May 2011}}</ref><ref>{{cite news|last1=Mulgrew|first1=John|title=Team GB Olympic name row still simmering in Northern Ireland|url=http://www.belfasttelegraph.co.uk/news/northern-ireland/team-gb-olympic-name-row-still-simmering-in-northern-ireland-28776939.html|accessdate=9 March 2015|work=Belfast Telegraph|date=2 August 2012}}</ref>。

形容詞の「British」は、イギリスに関する事項への言及によく用いられる。「British」に明白な法的含意はないが、イギリスの市民権及び[[:en:British nationality law|国籍に関する事項]]への言及に法律上用いられる<ref name="Bradley">{{cite book |url=http://books.google.com/?id=HT_GS2zgN5QC&pg=PA36 |title=Constitutional and administrative law |volume=1 |page=36 |author=Bradley, Anthony Wilfred |author2=Ewing, Keith D. |edition=14th |publisher=Pearson Longman |location=Harlow |year=2007 |isbn=978-1-4058-1207-8}}</ref>。イギリスの国民は、自らの国民性を表現するのに多数の異なる用語を用い、自らを[[イギリス人]]であるか、[[イングランド人]]、[[スコットランド人]]、[[ウェールズ人]]、[[:en:People of Northern Ireland|北アイルランド人]]、[[アイルランド人]]<ref>{{cite web |url=http://www.ark.ac.uk/nilt/2010/Community_Relations/NINATID.html |title=Which of these best describes the way you think of yourself? |year=2010 |work=Northern Ireland Life and Times Survey 2010 |publisher=ARK&nbsp;– Access Research Knowledge |accessdate=1 July 2010}}</ref>であるか、またはその両方であると見なし得る<ref>{{cite book |url=http://books.google.com/?id=u8gZklxHTMUC&pg=PA275 |title=Regionalism after regionalisation:Spain, France and the United Kingdom |pages=275–277 |author=Schrijver, Frans |publisher=Amsterdam University Press |year=2006 |isbn=978-90-5629-428-1}}</ref>。

2006年、{{仮リンク|イギリスのパスポート|en|British passport}}に新デザインが導入された。新パスポートの1ページ目には、[[英語]]、[[ウェールズ語]]、[[スコットランド・ゲール語]]で正式国名が記載されている<ref>{{cite news|url=http://www.guardian.co.uk/commentisfree/2010/dec/11/ian-jack-saddened-by-scotland-going-gaelic |location=London |work=The Guardian |first=Ian |last=Jack |title=Why I'm saddened by Scotland going Gaelic |date=11 December 2010}}</ref>。ウェールズ語での正式国名は"Teyrnas Unedig Prydain Fawr a Gogledd Iwerddon"であり、政府のウェブサイト上での略名は"Teyrnas Unedig"であるが<ref>{{cite web|url=http://www.direct.gov.uk/cy/Governmentcitizensandrights/LivingintheUK/DG_10012517CY|title=Ffeithiau allweddol am y Deyrnas Unedig|publisher=Directgov&nbsp;– Llywodraeth, dinasyddion a hawliau]|archiveurl=https://web.archive.org/web/20120924102112/http://www.direct.gov.uk/cy/Governmentcitizensandrights/LivingintheUK/DG_10012517CY|archivedate=2012年9月24日|accessdate=8 March 2015}}</ref>、通常は語形変化した形"Y Deyrnas Unedig"から"DU"と略される。スコットランド・ゲール語での正式国名は"Rìoghachd Aonaichte Bhreatainn is Èireann a Tuath"であり、略名は"Rìoghachd Aonaichte"である。

==歴史==
{{ブリテンの歴史}}
{{main|イギリスの歴史}}
[[ファイル:Descriptio Prime Tabulae Europae.jpg|thumb|left|[[クラウディオス・プトレマイオス|プトレマイオス]]の『[[地理学 (プトレマイオス)|地理学]]』に基づく地図、アルビオンと[[:en:Hibernia|ヒベルニア]](現在のアイルランド)の文字が見える]]
[[ファイル:Lenepveu, Jeanne d'Arc au siège d'Orléans.jpg|thumb|left|[[ジャンヌ・ダルク]]]]
{{Clear}}

古代のグレートブリテン島は[[アルビオン]]と呼ばれた。ラテン語起源で、ドーバーの白い崖に由来するとされる。

1066年に[[ノルマンディー公]]であった[[ウィリアム1世 (イングランド王)|ウィリアム征服王]] (William the Conqueror) が[[ノルマン・コンクエスト|イングランドを征服]]し、大陸の進んだ[[封建制]]を導入して、[[王国]]の体制を整えていった。人口と[[経済力]]に勝るイングランドがウェールズとスコットランドを圧倒していった。

13世紀、[[第一次バロン戦争]]・[[第二次バロン戦争]]で[[フランス]]に政治を左右された。1282年にウェールズ地方にもイングランドの州制度がしかれた。14-15世紀にわたりフランスと[[百年戦争]]を展開したが、1373年に[[英葡永久同盟]]を結んだ。

[[ばら戦争]]を勝ち抜いた[[ランカスター朝]]は[[閨閥]]にバイエルン公でホラント伯の[[ヴィルヘルム1世 (バイエルン公)|ヴィルヘルム1世]]を迎えた。1497年、[[ジョン・カボット]]が北米海岸を発見した。1514年、[[検閲]]できない外国商人飛脚が設立された。1534年、[[国王至上法]]が出た。1536年及び1543年の[[:en:Laws in Wales Acts 1535 and 1542|統一法]]の下、スコットランドを正式に併合した({{仮リンク|ウェールズ法諸法|en|Laws in Wales Acts 1535–1542}})。1559年、キリスト教が[[イングランド国教会]]統一された。1562年フランスで[[ユグノー戦争]]が起こってユグノーが移ってきた。亡命者トレンチ家はイギリスで[[:en:Earl of Clancarty|クランカートリー伯]]となった<ref>Samuel Smiles, ''The Huguenots:Their Settlements, Churches, and Industries in England and Ireland'', Genealogical Publishing Com, 1868, pp.313-314.</ref>。1588年、[[アルマダの海戦]]でカトリック勢力を破った。1598年、[[ハンザ同盟]]の在ロンドン基地を閉鎖した。

[[ファイル:London.bankofengland.arp.jpg|thumb|[[イングランド銀行]]]]
1600年[[イギリス東インド会社]]ができた。1603年にイングランドとスコットランドが[[同君連合]]を形成した。そして[[ヘンリー・ハドソン]]や[[ウィリアム・バフィン]]が北米探検に活躍した。1620年、[[ピルグリム・ファーザーズ]]が北米に上陸し、またフランスでユグノーが反乱しだした。1628年に[[権利の請願]]がなされ、翌年に[[リシュリュー]]がユグノーと和解した。1639-1640年、スコットランド王国に国教会を強制しようとイングランドは二度の司教戦争を挑むが共に敗れてしまった。そして矛先をアイルランド王国へ変えて、[[チャールズ1世 (イングランド王)|チャールズ1世]]、[[オリバー・クロムウェル]]、[[ウィリアム3世 (イングランド王)|ウィリアム3世]]の3人が17世紀末まで苛め抜いた。ウィレム3世は[[ルイ14世]]に迫害されたユグノーに支えられ、1694年[[イングランド銀行]]を設立した。1702年、ユグノーだった[[:en:Matthew Decker|マシュー・デッカー]]がロンドンへ来た。1704年にジブラルタルを占領し、[[カトリック]]勢力を地中海に封じた。1707年の合同法で、イングランドとスコットランドは合邦しグレートブリテン王国となった。[[ピューリタン]]とユグノーが商売敵のカトリックに対し統一戦線を組み上げたのである。[[イギリス帝国]]の手が届く世界各地で、宗教と経済が不可分にからみあった紛争が続いた。植民地の争奪戦だけでなく、[[ロシア帝国]]とアメリカ合衆国で利権を工作するときも彼らは常に優位であった。繊維業における[[産業革命]]は、綿花を輸出する[[アメリカ合衆国]]へ通貨を独占的に供給した。

[[ファイル:Battle of Waterloo 1815.PNG|thumb|ユグノーから[[:en:Baron Northwick|ノースウィック男爵]]が出た頃、イギリスは[[対仏大同盟]]の主役であった。連合国が[[ワーテルローの戦い]]で勝利し、[[ナポレオン戦争]]が終息した。こうして[[パクス・ブリタニカ]]の時代が到来した。]]
1801年の合同法でアイルランド王国と合邦し、グレートブリテン及びアイルランド連合王国となった<ref>アイルランドにもユグノーが地位を占めていた。[[:en:Baron Rendlesham|レンドルシャム男爵]]など。</ref>。しかし[[アイルランド共和軍]]は健在である。統一戦線としては、[[ジョージ4世 (イギリス王)|ジョージ4世]]の家柄・勲章、[[フリーメーソン]]加入、すべてが戦利品であった。フランス王が再びカトリックを強制することはないだろうし、もはや[[神聖ローマ帝国]]もなくなっていた。[[ベルギー]]を独立させ、[[阿片戦争]]に勝利し、統一戦線は鉄道・通信の独占に注力した。しかし統一戦線は事をやりすぎる癖があった。[[ルイ16世]]には忌まわしき[[フォンテーヌブローの勅令]]を破棄させれば十分であったが、[[フランス革命]]が[[ナポレオン]]を台頭させて神聖ローマだけでなく統一戦線まで脅かした。支援した[[プロイセン王国]]がロシアと組んで[[オスマン帝国]]を攻撃するのも都合がよかった。しかし[[普墺戦争]]で[[キール運河]]の利権をとられそうになったり、[[普仏戦争]]で南ドイツ連邦が水の泡となったり、[[オスマン債務管理局]]の利権を[[ドイツ帝国]]に奪われたりして、ベルギーの統一戦線は飼い犬に手を噛まれた気持ちになった。

「[[栄光ある孤立]]」と謳われた外交方針は[[エドワード7世 (イギリス王)|エドワード7世]]のときに放棄された。[[1902年]]には[[日本]]とも[[日英同盟]]を締結した。彼らはドイツを[[第一次世界大戦]]で敵対国として敗戦後の[[ヴァイマル共和政]]に対して多額の賠償金による債務奴隷にした。しかし、アメリカ合衆国に対する影響力でイギリスはドイツにひけをとった。1926年には[[バルフォア報告書]]が提出された。イギリスは[[ラザード]]を支配したが、[[太平洋]]は支配できなかった。[[ウィンザー朝]]の[[ジョージ5世 (イギリス王)|ジョージ5世]]による治世、[[デビッド・ロイド・ジョージ]]政権下の[[1922年]]に[[英愛条約]]が発効され、北部6州(北アイルランド;アルスター9州の中の6州)を除く26州がアイルランド自由国(現[[アイルランド|アイルランド共和国]])として独立し、[[1927年]]に現在の名称「'''グレートブリテン及び北アイルランド連合王国'''」へと改名した。なお、カントリーの一つであるスコットランドが独立すべきかどうかを問う住民投票が2014年9月に実施されたが独立は否決された<ref>{{cite web|url=http://www.cnn.co.jp/world/35023094.html|title=スコットランド独立の是非を問う住民投票実施へ 英国|author=<code>CNN.co.jp</code>|accessdate=2012-10-16}}</ref>。1925年受託者法([[:en:Trustee Act 1925|Trustee Act 1925]])の第61条は、裁判所に、公生かつ合理的に行動し、免責されるのが当然である受託者を、信託違反の責任から免除する権限を与えた<ref>Trustee Act, 1925. Article 61. "If it appears to the court that a trustee, whether appointed by the court or otherwise, is or may be personally liable for any breach of trust, whether the transaction alleged to be a breach of trust occurred before or after the commencement of this Act, but has acted honestly and reasonably, and ought fairly to be excused for the breach of trust and for ommitting to obtain the directions of the court in the matter in which he committed such breach, then the court may reliave him either wholly or partly from personal liability for the same."</ref><ref>1958年信託変更法([[:en:Variation of Trusts Act 1958|Variation of Trusts Act 1958]])は、信託を変更し、かつ受益者の利益のために信託財産を処理することを認可する広い権限を、裁判所に与えている。</ref>。この立法をなした[[イギリス議会]]は、[[世界恐慌]]が[[投資信託]]を通し大衆化した歴史にある程度の責任がある。イギリス投資信託全体の資産構成に占める下位証券の割合は、1933年で36.2%、1935年で42.0%、1938年で53.5%に上昇していった<ref>[[証券取引委員会]] ''Investment Trusts and Investment Companes'', Part 2, 連邦政府出版局 1939年 52頁;H.Burton and D.C.Corner, ''Investment and Unit Trusts in britain and America'', Elek Book, London, 1968, p.68.</ref>。

[[1939年]]の[[アドルフ・ヒトラー]]総統の[[国家社会主義ドイツ労働者党|ナチ党]]率いる[[ナチス・ドイツ]]が[[ポーランド]]に侵攻し、[[フランス]]とともに宣戦布告を行い、[[バトル・オブ・ブリテン]]をはじめ[[西部戦線 (第二次世界大戦)|ヨーロッパ戦線]]では対独伊戦争、[[太平洋戦争|太平洋戦線]]では対日戦争を経験し、アメリカ合衆国の[[民主党 (アメリカ)|民主党]][[フランクリン・ルーズベルト]]大統領と[[大西洋憲章]]を共同で提唱した保守党の[[ウィンストン・チャーチル]]政権による[[挙国一致内閣]]の下に勝利を得た[[第二次世界大戦]]後、[[イギリス軍]]はドイツの[[ハンブルク]]や[[ハノーファー]]を占領し、旧[[西ドイツ]]の形成の一役を担った。アメリカ合衆国は旧南ドイツ連邦と[[オーストリア]]西部を占領した。アメリカ合衆国の占領地域は[[オランダ]]と歴史がつながっており、[[戦間期]]にまして欧州東西の資本が錯綜した。

イギリスは、[[1945年]]の[[冷戦]]開始以降にかけて政治経済その他多くの面でアメリカ合衆国に覇権を譲った。また、[[資本主義]]・[[自由主義]]陣営の[[西側諸国]]の一国として[[ソビエト連邦]]とは敵対しながら、政治面では[[労働党 (イギリス)|労働党]]の[[クレメント・アトリー]]政権が「'''[[ゆりかごから墓場まで]]'''」をスローガンに[[福祉国家]]を作り上げた。経済面ではイングランド銀行が[[ブレトンウッズ協定|ブレトンウッズ体制]]をめぐる駆け引きに競り負け、1960年代のポンド危機と1970年代のセカンダリー・バンキング危機に遭い、「[[英国病]]」とまで呼ばれる[[景気後退|不景気]]に苦しんだ。産業面では戦前から[[ゼネラル・エレクトリック]]に[[産業革命]]の威光を奪われていた。アトリー失脚後は、保守党へ政権交代となりチャーチルが首相に再任する。

第二次大戦中イギリスは帝国内で最大規模の人口を誇る[[イギリス領インド帝国|インド]]に対して、ヨーロッパ、太平洋で複数の戦線を維持し、又城内平和を維持するため戦後[[インド]]の地位に対して大幅な譲歩をせざるを得なかった。イギリス政府は1947年にインド独立法を承認し、[[印パ分離独立|インドとパキスタンの独立]]を、翌[[1948年]]にはセイロン([[スリランカ]])の独立を承認した。又大戦中に日本の支配下にあったビルマ、マレーでもイギリス支配下に復することに混乱が見られ、[[1948年]]に[[ビルマ]](ミャンマー)の[[1957年]]に[[マレーシア]]の独立を承認した。

[[1960年代]]に入るとフランス領西アフリカの独立要求を期に[[アフリカ]]諸国の独立運動が活発化し、[[1960年]]に[[ナイジェリア]]が、[[1962年]]に[[ウガンダ]]が、[[1963年]]に[[ケニア]]が、[[1964年]]に[[マラウイ]]と[[ザンビア]]がイギリスから独立を宣言した。又[[1961年]]に[[南アフリカ共和国|南アフリカ]]が、[[1966年]]に[[ローデシア]]が[[アパルトヘイト]]維持のためイギリスからの独立を宣言した。

[[1956年]]には[[エジプト]]が[[スエズ運河]]の国有化を宣言し、同地帯を占領したためイギリス、フランス、[[イスラエル]]との間で戦闘が勃発した。これが[[第二次中東戦争]](スエズ危機)である。英仏は国際世論の支持を得られなかったためスエズから撤退し、[[地中海]]と[[紅海]]を結ぶスエズ運河の利権を喪失した。またエジプトの行動に励まされて中東地域でも独立運動が刺激され、[[1971年]]に[[バーレーン]]、[[カタール]]、[[アラブ首長国連邦]]がイギリスから独立した。

残る最大のイギリス植民地は[[香港]]だけになったが、これも1984年にマーガレット・サッチャー首相と[[トウ小平|鄧小平]][[中華人民共和国]]中央軍事委員会主席の間で行われた英中首脳会談で新界の租借期限が切れる1997年に割譲地も含めて一斉に中国に返還されることになった。[[香港返還|香港を返還]]したことで、イギリスは主要な植民地のほぼ全てを喪失することになり、世界の7つの海を跨いだ[[イギリス帝国]]は消滅していった。

[[1964年]]には[[ハロルド・ウィルソン]]が首相に就任し、アトリー以来13年ぶりに労働党が政権に復帰する。[[1969年]]に[[イングランド]]、[[ウェールズ]]、 [[スコットランド]]、[[1973年]]に[[北アイルランド]]で死刑制度が一部例外を除き廃止された。また、ウィルソン労働党政権下で、[[妊娠中絶]]の合法化、[[死刑]]制度の廃止及び[[同性愛]]の非刑罰化([[ソドミー法]]の廃止)を含む社会的改革がなされ、通貨[[スターリング・ポンド|ポンド]]の平価切り下げや、日本の[[放送大学]]の模倣ともなった[[大学通信教育|通信制公立大学]]である[[オープン大学]]の設置などの政策が実施された。

1980年代に成立した[[保守党 (イギリス)|保守党]]の[[マーガレット・サッチャー]]政権は、[[新自由主義]]による[[構造改革]]([[ネオリベラリズム]]・[[サッチャリズム]]に基づく[[民営化]]・[[行政改革]]・[[規制緩和]])を急進させて([[小さな政府]]志向・[[自由主義国家論]])、多くの[[失業]]者を出した。地方経済は不振を極め、ロンドンを中心に[[金融]]産業などが成長した。

1990年代、政権は保守党の[[ジョン・メージャー]]から労働党の[[トニー・ブレア]]に交代し、イギリスは[[市場]]化一辺倒の[[政策]]を修正しつつかつての重厚な福祉国家にも逆戻りしない「[[第三の道]]」への路線に進むことになった。また、[[1998年]]人権法を制定し、[[死刑]]制度が完全に廃止された。この頃からイギリスは久しぶりの好況に沸き、「老大国」のイメージを払拭すべく「'''[[クール・ブリタニア]]'''」と呼ばれるイメージ戦略・[[文化政策]]に力が入れられるようになった。

2000年代〜2010年代、[[21世紀]]に突入し、労働党の[[ゴードン・ブラウン]]、保守党の[[デーヴィッド・キャメロン]]と政権が続く。

[[2014年]]からは、[[同性結婚]]が合法化された。

[[2016年]][[6月23日]]に[[イギリスの欧州連合離脱是非を問う国民投票]]が実施されその結果、僅差をもって離脱賛成派が過半数を占めたため、[[イギリスの欧州連合離脱]](通称:ブレグジット、Brexit)が決定された。

これを受けて、キャメロン首相兼保守党党首が責任を取る形で辞任を表明し、[[テリーザ・メイ]]が、サッチャーに続く2人目のイギリスの女性首相兼保守党党首として2016年[[7月13日]]に就任した。メイ政権は、新たに[[欧州連合離脱省]]を設置した。

結果として、[[2020年]][[1月31日]]午後11時([[グリニッジ標準時|GMT]])にイギリスは[[欧州連合]](EU)から脱退した<ref>{{Cite web|url=https://mainichi.jp/articles/20200201/k00/00m/030/008000c|title=英国がEU離脱 加盟国の離脱は初|publisher=毎日新聞|date=2020-02-01|accessdate=2020-02-01}}</ref>。

==地理==
{{main|イギリスの地理}}
[[ファイル:Uk topo en.jpg|thumb|200px|イギリスの地形図]]
[[ファイル:BenNevis2005.jpg|thumb|[[ブリテン諸島]]最高峰の[[ベン・ネビス山]]]]
イギリスはグレートブリテン島のイングランド、ウェールズ、スコットランド、およびアイルランド島北東部の北アイルランドで構成されている。この2つの大きな島と、その周囲大小の島々を[[ブリテン諸島]]と呼ぶ。グレートブリテン島は中部から南部を占めるイングランド、北部のスコットランド、西部のウェールズに大別される。アイルランド島から北アイルランドを除いた地域はアイルランド共和国がある。

北アイルランドとアイルランド共和国の国境の他に、イギリスは[[大西洋]]に囲まれ、東に[[北海]]、南に[[イギリス海峡]]がある。[[アイリッシュ海]]は、グレートブリテン島とアイルランド島の間に位置する。イギリスの総面積は243,610km<sup>2</sup>であり、[[国の面積順リスト|世界第78位]]及び[[:en:List of European countries by area|ヨーロッパ第11位]]。

イングランドの大部分は<!--rolling lowland terrain-->岩の多い低地からなり、北西の山がちな地域([[湖水地方]]のカンブリア山脈)、北部(ペニンネスの湿地帯、ピーク・ディストリクトの[[石灰岩]]丘陵地帯、デールと呼ばれる渓谷、[[パーベック島]]、[[リンカンシャー]]の石灰岩質の丘陵地帯)から南イングランドの泥炭質のノース・ダウンズ、サウス・ダウンズ、チルターンにいたる。イングランドを流れる主な河川は、[[テムズ川]]、[[セヴァーン川]]、[[トレント川]]、[[ウーズ川]]である。主な都市はロンドン、[[バーミンガム]]、[[ヨーク (イングランド)|ヨーク]]、[[ニューカッスル・アポン・タイン]]など。イングランド南部の[[ドーバー (イギリス)|ドーヴァー]]には、[[英仏海峡トンネル]]があり、対岸のフランスと連絡する。イングランドには標高 1000m を超える地点はない。

ウェールズは山がちで、最高峰は標高 1,085m の[[スノードン山]]である。本土の北に[[アングルシー島]]がある。ウェールズの首都また最大の都市は[[カーディフ]]で、南ウェールズに位置する。

スコットランドは地理的に多様で、南部および東部は比較的標高が低く、ベン・ネビス山がある北部および西部は標高が高い。ベン・ネビス山はイギリスの最高地点で標高 1343 m である。スコットランドには数多くの半島、湾、ロッホと呼ばれる湖があり、グレート・ブリテン島最大の淡水湖である[[ネス湖|ロッホ・ネス]]もスコットランドに位置する。西部また北部の海域には、[[ヘブリディーズ諸島]]、[[オークニー諸島]]、[[シェトランド諸島]]を含む大小さまざまな島が分布する。スコットランドの主要都市は首都[[エディンバラ]]、[[グラスゴー]]、[[アバディーン]]である。

北アイルランドは、アイルランド島の北東部を占め、ほとんどは丘陵地である。中央部は平野で、ほぼ中央に位置する[[ネイ湖]]はイギリス諸島最大の湖である。主要都市は[[ベルファスト]]と[[ロンドンデリー|デリー]]。

現在イギリスは大小あわせて1098ほどの島々からなる。ほとんどは自然の島だが、いくつかは[[クランノグ]]といわれる、過去の時代に石と木を骨組みに作られ、しだいに廃棄物で大きくなっていった人工の島がある。

イギリスの大半はなだらかな丘陵地及び平原で占められており、国土のおよそ90%が可住地となっている。そのため、国土面積自体は[[日本]]のおよそ3分の2([[本州]]と[[四国]]を併せた程度)であるが、[[可住地面積]]は逆に日本の倍近くに及んでいる。イギリスは[[森林]]も少なく、日本が国土の3分の2が森林で覆われているのに対し、イギリスの[[森林率]]は11%ほどである<ref>{{Cite web |url=http://yoshio-kusano.sakura.ne.jp/nakayamakouen6newpage3.html |title=中山徹奈良女子大教授の記念講演6 どうやって森を再生するかイギリスの例 |publisher=日本共産党宝塚市議 草野義雄 |accessdate=2014-5-10 |archiveurl=https://web.archive.org/web/20140512220911/http://yoshio-kusano.sakura.ne.jp/nakayamakouen6newpage3.html |archivedate=2014年5月12日 |deadlinkdate=2018年3月 }}</ref>。

その他、{{仮リンク|領土紛争の一覧|en|List of territorial disputes|label=紛争中}}の[[フォークランド諸島]]、[[ジブラルタル]]、[[イギリス領インド洋地域|インド洋地域]]を含む[[イギリスの海外領土|14の海外領土]]を有する<ref>{{cite web |url=http://www.fco.gov.uk/en/about-us/what-we-do/overseas-territories |title=Working with Overseas Territories |publisher=[[:en:Foreign and Commonwealth Office|Foreign and Commonwealth Office]] |accessdate=3 May 2011}}</ref>。[[ガーンジー]]、[[ジャージー]]、[[マン島]]はイギリスの一部ではなく、イギリスの君主をともに君主とし、[[イギリス政府]]が防衛及び国際的表示に対して責任を負う[[イギリスの王室属領|王室属領]]である<ref>{{cite web |url=http://www.direct.gov.uk/en/Governmentcitizensandrights/LivingintheUK/DG_10012517 |title=Key facts about the United Kingdom |accessdate=3 May 2011 |publisher=[[:en:Directgov|Directgov]] |quote=The full title of this country is 'the United Kingdom of Great Britain and Northern Ireland'. 'The UK' is made up of England, Scotland, Wales and Northern Ireland. 'Britain' is used informally, usually meaning the United Kingdom. 'Great Britain' is made up of England, Scotland and Wales. The Channel Islands and the Isle of Man are not part of the UK. |archiveurl=http://webarchive.nationalarchives.gov.uk/20121015000000/http:/www.direct.gov.uk/en/Governmentcitizensandrights/LivingintheUK/DG_10012517 |archivedate=2012年10月15日 |deadlinkdate=2018年3月 }}</ref>。

===主要都市===
{{Main|イギリスの都市の一覧}}
イギリスは四つの非独立国であるイングランド、スコットランド、ウェールズ、北アイルランドより構成される。それぞれの国は首都を持ち、ロンドン(イングランド)、エディンバラ(スコットランド)、カーディフ(ウェールズ)、ベルファスト(北アイルランド)がそれである。中でもイングランドの首都であるロンドンは、イギリス連合王国の首都としての機能も置かれている。

イングランドの[[首都]]ロンドンは、[[ヨーロッパ]]第2の規模の都市的地域及び[[ユーロスタット]]によれば[[欧州連合]]最大の約1,400万人の人口を有する[[:en:London commuter belt|都市圏]]であり、重要な[[世界都市]]及び[[金融センター]]である<ref name="appsso.eurostat.ec.europa.eu show">{{cite web |url=http://appsso.eurostat.ec.europa.eu/nui/show.do?dataset=met_pjanaggr3&lang=en |title=Metropolitan Area Populations |publisher=Eurostat |date=30 August 2012 |accessdate=4 May 2013}}</ref><ref>{{cite web|url=https://www.cia.gov/library/publications/the-world-factbook/geos/uk.html|title=The World Factbook|date=1 February 2014|work=[[Central Intelligence Agency]]|accessdate=23 February 2014}}</ref>。

ウェールズ、スコットランド、北アイルランドの首都は各々カーディフ、エディンバラ、ベルファストである。
[[ファイル:Population density UK 2011 census.png|thumb|right|人口分布(2011年)]]

{| class="infobox" style="text-align:center; width:100%; margin-right:10px; font-size:100%"
! colspan="10" style="background:#e9e9e9; padding:0.3em; line-height:1.2em;"| '''イギリスの主要都市'''
|-
!rowspan=30|
[[ファイル:2019 Greenwich Peninsula & Canary Wharf.jpg|150px]]<br /><small>[[ロンドン]]</small><br />[[ファイル:Birmingham Skyline from Edgbaston Cricket Ground crop.jpg|150px]]<br /><small>[[バーミンガム]]</small><br />
! style="text-align:center; background:#f5f5f5;"| <small>#</small>
! style="text-align:left; background:#f5f5f5;"| 都市名
! style="text-align:left; background:#f5f5f5;"| [[イギリスの地方行政区画|行政区画]]
! style="text-align:center; background:#f5f5f5;"| 人口
! style="text-align:center; background:#f5f5f5;"| <small>#</small>
! style="text-align:left; background:#f5f5f5;"| 都市名
! style="text-align:left; background:#f5f5f5;"| [[イギリスの地方行政区画|行政区画]]
! style="text-align:center; background:#f5f5f5;"| 人口
!rowspan=21|
[[ファイル:Leeds CBD at night.jpg|150px]]<br /><small>[[リーズ]]</small><br />[[ファイル:Glasgow and the Clyde from the air (geograph 4665720).jpg|150px]]<br /><small>[[グラスゴー]]</small><br />
|-
| style="background:#f0f0f0"| 1 ||align=left | '''[[ロンドン]]''' || {{ENG}} || 8,908,081人 || 11 ||align=left | '''[[コヴェントリー]]''' || {{ENG}} || 366,785人
|-
| style="background:#f0f0f0"| 2 ||align=left | '''[[バーミンガム]]''' || {{ENG}} || 1,141,374人 || 12 ||align=left | '''[[カーディフ]]''' || {{Flagicon|WAL}}[[ウェールズ]] || 362,800人
|-
| style="background:#f0f0f0"| 3 ||align=left | '''[[リーズ]]''' || {{ENG}} || 789,194人 || 13 ||align=left | '''[[ベルファスト]]''' || {{Flagicon|北アイルランド}}[[北アイルランド]] || 340,200人
|-
| style="background:#f0f0f0"| 4 ||align=left | '''[[グラスゴー]]''' || {{SCO}} || 626,410人 || 14 ||align=left | '''[[レスター]]''' || {{ENG}} || 329,839人
|-
| style="background:#f0f0f0"| 5 ||align=left | '''[[シェフィールド]]''' || {{ENG}} || 582,506人 || 15 ||align=left | '''[[ノッティンガム]]''' || {{ENG}} || 321,500人
|-
| style="background:#f0f0f0"| 6 ||align=left | '''[[マンチェスター]]''' || {{ENG}} || 547,627人 || 16 ||align=left | '''[[ニューカッスル・アポン・タイン|ニューカッスル・アポン・タイン]]''' || {{ENG}} || 300,196人
|-
| style="background:#f0f0f0"| 7 ||align=left | '''[[ブラッドフォード (イングランド)|ブラッドフォード]]''' || {{ENG}} || 537,173人 || 17 ||align=left | '''[[プリマス]]''' || {{ENG}} ||  263,100人
|-
| style="background:#f0f0f0"| 8 ||align=left | '''[[リヴァプール]]''' || {{ENG}} || 494,814人 || 18 ||align=left | '''[[ウルヴァーハンプトン]]''' || {{ENG}} || 262,008人
|-
| style="background:#f0f0f0"| 9 ||align=left | '''[[エディンバラ]]''' || {{SCO}} || 488,050人 || 19 ||align=left | '''[[キングストン・アポン・ハル|キングストン・アポン・ハル]]''' || {{ENG}} || 260,645人
|-
| style="background:#f0f0f0"| 10 ||align=left | '''[[ブリストル]]''' || {{ENG}} || 463,400人 || 20 ||align=left | '''[[ストーク=オン=トレント|ストーク・オン・トレント]]''' || {{ENG}} || 255,833人
|}
{{Clear}}
4位以下の都市人口が僅差であり順位が変わりやすい。2006年以降はロンドン、バーミンガム、リーズ、グラスゴー、シェフィールドの順となっている。

===気候===
イギリスの[[気候]]は2つの要因によって基調が定まっている。まず、[[メキシコ湾流]]に由来する暖流の北大西洋海流の影響下にあるため、北緯50度から60度という高緯度にもかかわらず温暖であること、次に中緯度の偏西風の影響を強く受けることである。以上から[[西岸海洋性気候]] (Cfb) が卓越する。[[大陸性気候]]はまったく見られず、気温の年較差は小さい。

メキシコ湾流の影響は冬季に強く現れる。特に西部において気温の低下が抑制され、気温が西岸からの距離に依存するようになる。夏季においては緯度と気温の関連が強くなり、比較的東部が高温になる。水の蒸散量が多い夏季に東部が高温になることから、年間を通じて東部が比較的乾燥し、西部が湿潤となる。

降水量の傾向もメキシコ湾流の影響を受けている。東部においては、降水量は一年を通じて平均しており、かつ、一日当たりの降水量が少ない。冬季、特に風速が観測できない日には霧が発生しやすい。この傾向が強く当てはまる都市としてロンドンが挙げられる。西部においては降水量が2500mmを超えることがある。

首都ロンドンの年平均気温は12.8度、1月の平均気温は6.7度、7月の平均気温は19.5度<ref>[https://www.weatheronline.co.uk/weather/maps/city?FMM=1&FYY=2001&LMM=12&LYY=2017&WMO=03779&CONT=ukuk&REGION=0003&LAND=UK&ART=TEM&R=0&NOREGION=1&LEVEL=162&LANG=en&MOD=tab London Weather Center 2001年1月から2017年12月までの平均]</ref>、年平均降水量は750.6mmとなっている。

==政治==
[[ファイル:Palace of Westminster, London - Feb 2007.jpg|thumb|[[イギリスの議会|英国議会]]が議事堂として使用する[[ウェストミンスター宮殿]]]]
{{main|イギリスの政治|イギリスの憲法|英国法|英米法}}
[[政体]]は、イギリスの君主を[[元首]]に戴く[[立憲君主制]]であり、内閣が議会の信任に基づいて存在する[[議院内閣制]]を採用する<ref>[http://www.royal.gov.uk/MonarchUK/HowtheMonarchyworks/Whatisconstitutionalmonarchy.aspx The British Monarchy, ''What is constitutional monarchy?'']. Retrieved 17 July 2013</ref><ref>[https://www.cia.gov/library/publications/the-world-factbook/geos/uk.html CIA, ''The World Factbook'']. Retrieved 17 July 2013</ref>。
===元首===
{{現在のイギリスの君主}}
1952年{{0}}2月{{0}}6日以降のイギリス女王(君主)は、[[ウィンザー朝]]第4代君主・[[エリザベス2世]]である。

===法===
[[イギリスの憲法]]は一つに成典化されていない[[不文憲法]]であり、[[制定法]](議会制定法だけでなく[[マグナ・カルタ]]のような国王と貴族の契約も含む)や[[判例法]]、歴史的文書及び[[慣習法]](憲法的習律と呼ばれる)などが憲法を構成している。これらは他の法律と同様に議会で修正可能なため、[[軟性憲法]]であると言える(ただし、伝統的に憲法を構成する法律については簡単に改正されることはない)。憲法を構成する慣習法の一つに「'''国王は君臨すれども統治せず'''」とあり、女王(国王)の権能は極めて儀礼的である。

このように、世界でも最も早い段階から立憲君主制と[[法の支配]]を採用し、また[[立法権]]優位の[[議会主権|議会主義]]が発達しており、[[議院内閣制]]([[ウェストミンスター・システム]])や[[政党制]]([[複数政党制]])など、現代の多くの国家が採用している[[民主主義]]の諸制度が発祥した国である。

===内政===
[[立法権]]は[[イギリスの議会|議会]]に、[[行政権]]は首相及び[[内閣 (イギリス)|内閣]]に、[[司法権]]は[[イギリス最高裁判所]]及び以下の下級[[裁判所]]によって行使される。

イギリスの議会は、上院([[貴族院 (イギリス)|貴族院]])と下院([[庶民院 (イギリス)|庶民院]])の[[二院制]]である。1911年に制定された[[議会法]](憲法の構成要素の一つ)により、「下院の優越」が定められている。議院内閣制に基づき、行政の長である首相は憲法的習律に従って下院第一党党首(下院議員)を国王が任命、閣僚は議会上下両院の議員から選出される。下院は単純[[小選挙区制]]による[[直接選挙]]([[普通選挙]])で選ばれるが、上院は非公選であり任命制である。近年、従来[[右派]]の保守党と[[左派]]の労働党により[[二大政党制]]化して来たが、近年では第三勢力の[[自由民主党 (イギリス)|自由民主党]](旧[[自由党 (イギリス)|自由党]]の継承政党)の勢力も拡大している。

ウェールズ、スコットランド、北アイルランドは各々異なる{{仮リンク|権限委譲 (イギリス)|en|Devolution in the United Kingdom|label=権限を委譲された}}政権を有しており<ref name="devoladmins">{{cite web|url=https://www.gov.uk/devolution-of-powers-to-scotland-wales-and-northern-ireland#devolved-administrations|title=Devolution of powers to Scotland, Wales, and Northern Ireland|publisher=United Kingdom Government|accessdate=17 April 2013|quote=In a similar way to how the government is formed from members from the two Houses of Parliament, members of the devolved legislatures nominate ministers from among themselves to comprise an executive, known as the devolved administrations...}}</ref><ref>{{cite news |url=http://news.bbc.co.uk/1/hi/education/7859034.stm |title=Fall in UK university students |work=BBC News |date=29 January 2009}}</ref><ref>{{cite web |url=http://www.transport-research.info/web/countryprofiles/uk.cfm |title=Country Overviews:United Kingdom |publisher=Transport Research Knowledge Centre |accessdate=28 March 2010 |archiveurl=https://web.archive.org/web/20100404062853/http://www.transport-research.info/web/countryprofiles/uk.cfm |archivedate=2010年4月4日 |deadlinkdate=2018年3月 }}</ref>、1996年に[[北アイルランド議会]]、1999年には[[スコットランド議会]]と[[ウェールズ議会]]が設置され、自治が始まった。スコットランドには主に[[スコットランド国民党]]による[[スコットランド独立運動]]が存在し、北アイルランドには20世紀から続く[[北アイルランド問題]]も存在する。
2016年{{0}}6月[[イギリスの欧州連合離脱是非を問う国民投票|欧州連合からの離脱を問う国民投票]]で賛成多数となり、1973年のEEC加盟以来の大陸との一体化が幕を閉じた([[ブレグジット]])。これを受けてキャメロン首相からメイ首相へ交代した。現任の首相は[[ボリス・ジョンソン]]。

===地方行政区分===
[[ファイル:Scotland Parliament Holyrood.jpg|thumb|[[スコットランド議会]]議事堂]]
{{main|イギリスの地方行政区画}}

連合王国の地方行政制度は次の各地方によって異なっている。
*{{Flag|ENG}}
*{{Flag|SCO}}
*{{Flag|WAL}}
*[[北アイルランド]]
このほか、連合王国には含まれないものの、連合王国がその国際関係について責任を負う地域として、海外領土および[[王室属領]]が存在する。

===外交・軍事===
[[ファイル:Donald Trump and Theresa May (33998675310) (cropped).jpg|thumb|left|[[2017年]][[1月27日]]、就任直後の[[ドナルド・トランプ]]米大統領(右)と[[ホワイトハウス]]で会談する[[テリーザ・メイ]]元英首相(左)]]
{{Main|イギリスの国際関係|イギリス軍}}
イギリスは19世紀から20世紀前半までの間、世界最高位の[[大国]]であった<ref>{{cite book |title=The First Industrial Nation:the Economic History of Britain, 1700–1914 |publisher=Routledge |location=London |author=Mathias, P. |year=2001 |isbn=0-415-26672-6}}</ref><ref name="ferguson">{{cite book |last=Ferguson |first=Niall |year=2004 |title=Empire:The rise and demise of the British world order and the lessons for global power |publisher=Basic Books |location=New York |isbn=0-465-02328-2}}</ref>。現在も[[列強]]であり続け、経済、文化、軍事、科学、政治で国際的な[[勢力圏|影響力を有する]]<ref>{{cite news |url=http://www.theaustralian.com.au/news/opinion/cameron-has-chance-to-make-uk-great-again/story-e6frg6zo-1225866975992 |author=Sheridan, Greg |title=Cameron has chance to make UK great again |accessdate=23 May 2011 |work=The Australian |location=Sydney |date=15 May 2010}}</ref><ref>{{cite news |url=http://www.independent.co.uk/news/uk/home-news/britain-is-now-most-powerful-nation-on-earth-8326452.html |author=Dugan, Emily |title=Britain is now most powerful nation on earth |accessdate=18 November 2012 |work=The Independent |location=London |date=18 November 2012}}</ref><ref name="David M. McCourt">{{cite book|last=McCourt|first=David|title=Britain and World Power Since 1945:Constructing a Nation's Role in International Politics|publisher=University of Michigan Press|year=28 May 2014|location=United States of America|pages=|isbn=0472072218|url=http://books.google.ie/books?id=lwpOnwEACAAJ&dq=Britain+and+World+Power+Since+1945:+Constructing+a+Nation%27s+Role+in+International+Politics&hl=en&sa=X&ei=TCJkU8TOE6mS7Abw14HIBg&ved=0CDIQ6AEwAA}}</ref>。

[[戦間期]]の[[国際連盟]]時代と同様、1946年の第1回[[国際連合安全保障理事会]]以来、同国は同理事会[[国際連合安全保障理事会常任理事国|常任理事国]]であり、[[G7]][[主要国首脳会議|G8]]、[[G20]]、[[北大西洋条約機構|NATO]]、[[欧州評議会]]、[[経済協力開発機構|OECD]] 、[[世界貿易機関|WTO]]の加盟国となっている。そして、アメリカ合衆国と歴史的に「'''特別な関係'''(Special relationship)」を持つ。アメリカ合衆国とヨーロッパ以外にも、1920年代までは日本と[[日英同盟]]を結んでいた友好同盟国であったため、[[大正]]時代の[[大日本帝国海軍]](現在の[[海上自衛隊]])は[[イギリス海軍]]の伝統に多大な影響を受けながら発展した。イギリスと密接な同盟国は、[[イギリス連邦|連邦国]]と他の[[英語圏]]の国家を含む。イギリスの世界的な存在と影響は、各国との相補関係と軍事力を通して拡大されている。それは、世界中で約80の軍事基地の設置と軍の配備を維持していることにも現れている<ref>{{cite web|url=http://www.globalpowereurope.eu/|title=Global Power Europe|publisher=<code>Globalpowereurope.eu</code>|language=英語|accessdate=2008-10-17}}</ref>。2011年の軍事支出は627億ドルと一定水準を保っている。

[[ファイル:Soldiers Trooping the Colour, 16th June 2007.jpg|thumb|軍旗分列行進式における[[近衛兵 (イギリス)|近衛兵]]]]
イギリスの[[軍隊]]は「イギリス軍」<ref>{{lang-en-short|British Armed Forces}}</ref>または「陛下の軍」<ref>{{lang-en-short|His/Her Majesty's Armed Forces}}</ref>として知られている。しかし、公式の場では「アームド・フォーシーズ・オブ・ザ・クラウン」<!-- 慣例がないため未翻訳 --><ref>{{lang-en-short|Armed Forces of the Crown}}</ref>と呼ばれる<ref>{{Cite web|url=http://www.raf.mod.uk/legalservices/p3chp29.htm|title=Armed Forces Act 1976, Arrangement of Sections|publisher=<code>raf.mod.uk</code>|language=英語|accessdate=2009-02-22|archiveurl=https://web.archive.org/web/20090221072352/http://www.raf.mod.uk/legalservices/p3chp29.htm|archivedate=2009年2月21日|deadlinkdate=2018年3月}}</ref>(クラウンは冠、王冠の意)。全軍の最高司令官はイギリスの君主であるが、それはあくまで名目上に過ぎず、首相が事実上の指揮権を有している。軍の日常的な管理は[[国防省 (イギリス)|国防省]]に設置されている[[国防委員会]]によって行われている。

イギリスの軍隊は各国の軍隊に比べて広範囲にわたる活動を行い、世界的な[[戦力投射]]能力を有する軍事大国の1つに数えられ、国防省によると[[軍事費]]は世界2位である。2008年現在、軍事費はGDPの2.5%を占めている<ref>{{Cite web|url=http://www.mod.uk/DefenceInternet/AboutDefence/Organisation/KeyFactsAboutDefence/DefenceSpending.htm|title=Defence Spending|publisher={{lang|en|Ministry of Defence}}|language=英語|accessdate=2008-01-06 }}</ref>。イギリス軍はイギリス本国と海外の領土を防衛しつつ、世界的なイギリスの将来的国益を保護し、国際的な平和維持活動の支援を任ぜられている。

2005年の時点で[[イギリス陸軍|陸軍]]は102,440名、[[イギリス空軍|空軍]]は49,210名、海軍([[イギリス海兵隊|海兵隊]]を含む)は36,320名の兵員から構成されており、イギリス軍の190,000名が現役軍人として80か国以上の国に展開、配置されている<ref>{{lang-en-short|Ministry of Defence}}「{{PDFlink|[http://www.mod.uk/NR/rdonlyres/6FBA7459-7407-4B85-AA47-7063F1F22461/0/modara_0405_s1_resources.pdf Annual Reports and Accounts 2004-05]|1.60&nbsp;MB}}」2006-05-14 閲覧。{{En icon}}</ref>。

イギリスは[[核兵器]]の保有を認められている5カ国の1つであり、{{仮リンク|国別軍事費の一覧|en|List of countries by military expenditures|label=軍事費は世界第5位又は第6位}}である<ref name="SIPRI">{{cite web |url=http://books.sipri.org/product_info?c_product_id=476 |title=The 15 countries with the highest military expenditure in 2013 (table) |publisher=[[:en:Stockholm International Peace Research Institute|Stockholm International Peace Research Institute]] |format=PDF |accessdate=4 May 2014 |archiveurl=https://web.archive.org/web/20150104033821/http://books.sipri.org/product_info?c_product_id=476 |archivedate=2015年1月4日 |deadlinkdate=2018年3月 }}</ref><ref name="iiss.org">[http://www.iiss.org/en/about%20us/press%20room/press%20releases/press%20releases/archive/2014-dd03/february-0abc/military-balance-2014-press-statement-52d7 The Military Balance 2014:Top 15 Defence Budgets 2013] (IISS)</ref>。[[核弾頭]]搭載の[[トライデント (ミサイル)|トライデント II]] [[潜水艦発射弾道ミサイル]] (SLBM) を運用している。イギリス海軍は、トライデント IIを搭載した[[原子力潜水艦]]4隻で[[核抑止]]力の任務に担っている。
{{See also|イギリスの大量破壊兵器}}

イギリス軍の幅広い活動能力にも関わらず、最近の国事的な国防政策でも協同作戦時に最も過酷な任務を引き受けることを想定している<ref>{{lang|en|Office for National Statistics}}、{{lang|en|UK 2005:The Official Yearbook of the United Kingdom of Great Britain and Northern Ireland}}、p. 89 {{En icon}}</ref>。イギリス軍が単独で戦った最後の戦争は[[フォークランド紛争]]で、全面的な戦闘が丸々3か月続いた。現在は[[ボスニア紛争]]、[[コソボ紛争]]、[[アフガニスタン紛争 (2001年-)|アフガニスタン侵攻]]、[[イラク戦争]]など、アメリカ軍やNATO諸国との[[連合作戦]]が慣例となっている。イギリス海軍の軽歩兵部隊であるイギリス海兵隊は、[[上陸戦|水陸両用作戦]]の任務が基本であるが、イギリス政府の外交政策を支援するため、軽歩兵部隊の特性を生かして海外へ即座に展開できる機動力を持つ。

==経済==
{{main|イギリスの経済}}
[[国際通貨基金|IMF]]によると、2015年のイギリスの[[国内総生産|GDP]]は2兆8584億ドルであり、世界5位、欧州では[[ドイツ]]に次ぐ2位である<ref name="GDP1">[https://www.imf.org/external/pubs/ft/weo/2016/02/weodata/weorept.aspx?sy=2015&ey=2015&scsm=1&ssd=1&sort=country&ds=.&br=1&c=112&s=NGDPD%2CNGDPDPC&grp=0&a=&pr.x=28&pr.y=7 World Economic Outlook Database, October 2016] IMF 2016年11月{{0}}3日閲覧。</ref>。同年の一人当たりのGDPは4万3902ドルである<ref name="GDP1"/>。[[人間開発指数]]は[[人間開発指数による国順リスト|世界第14位]]で「非常に高い」に分類される。

[[ファイル:City of London skyline from London City Hall - Oct 2008.jpg|thumb|250px|ロンドンは2016年に発表された「世界の都市総合力ランキング」において、世界1位と評価された<ref>[http://www.mori-m-foundation.or.jp/ius/gpci/ 世界の都市総合力ランキング(GPCI) 2016] 森記念財団都市戦略研究所 2016年10月31日閲覧。</ref>]]
首都ロンドンは2016年時点で[[ニューヨーク]]を上回る世界一の金融センターと評価されている<ref>[http://www.longfinance.net/global-financial-centres-index-20/1037-gfci-20.html Global Financial Centres Index 20] Z/yen 2016年11月{{0}}3日閲覧。</ref>。ロンドンの[[シティ・オブ・ロンドン|シティ]]には、世界屈指の[[証券取引所]]である[[ロンドン証券取引所]]がある。イギリスの[[外国為替市場]]の1日平均取引額はアメリカを上回り、世界最大である<ref>[http://www.bis.org/publ/rpfx16.htm Triennial Central Bank Survey of foreign exchange and OTC derivatives markets in 2016] 国際決済銀行(BIS) 2016年11月{{0}}3日閲覧。</ref>。[[富裕層|富裕層人口]]も非常に多く、金融資産100万ドル以上を持つ富裕世帯は約41万世帯と推計されており、アメリカ、日本、[[中華人民共和国|中国]]に次ぐ第4位である<ref name="Rich">[http://www.bcg.com/expertise_impact/publications/PublicationDetails.aspx?id=tcm:12-107081 BCG Global Wealth 2012]</ref>。また、金融資産1億ドル以上を持つ超富裕世帯は1,125世帯と推計されており、アメリカに次ぐ第2位である<ref name="Rich"/>。

[[18世紀]]の産業革命以降、近代において[[世界経済]]をリードする[[工業国]]で、[[造船]]や[[航空機]]製造などの[[工業|重工業]]から金融業や[[エンターテインメント|エンターテイメント]]産業に至るまで、様々な産業が盛んである。歴史的に造船業は特筆に値し、[[複式機関#船舶用複式蒸気機関の例|三段膨張機関]]が登場してから第一次世界大戦勃発までは世界の船の三分のニを生産した<ref>柏戸傳、「[https://hdl.handle.net/11266/1231 大戦間期日・英造船業の企業金融]」『立正経営論集』 2005年 37巻 2号, 立正大学経営学会</ref>。

しかしながら、19世紀後半からはアメリカ合衆国、ドイツ帝国の工業化により世界的優位は失われた。イギリスを含む世界金融資本がイギリス製造業への投資より、ドイツ・アメリカおよび植民地への投資を選好したためである。イギリス製造業はしだいにドイツ・フランスやアメリカ合衆国に立ち後れるようになってゆく。20世紀に入るころより国力は衰え始め、二度の世界大戦はイギリス経済に大きな負担を与えた。各地の植民地をほとんど独立させた1960年代後半には経済力はいっそう衰退した。

戦後の経済政策の基調は市場と国営セクター双方を活用する[[混合経済]]体制となり、左派の労働党は「[[ゆりかごから墓場まで]]」と呼ばれる公共福祉の改善に力を入れ、保守党も基本的にこれに近い政策を踏襲、1960年代には世界有数の[[福祉国家論|福祉国家]]になった。しかし、[[オイルショック]]を契機とした不況になんら実用的な手立てを打たなかったために、継続的な不況に陥り、企業の倒産やストが相次いだ。20世紀初頭から沈滞を続けたイギリス経済は深刻に行き詰まり、「[[英国病]]」とまで呼ばれた。

1979年に登場したサッチャー政権下で国営企業の民営化や各種規制の緩和が進められ、1980年代後半には海外からの直接投資や証券投資が拡大した。この過程で製造業や[[鉱業]]部門の労働者が大量解雇され、深刻な失業問題が発生。基幹産業の一つである[[自動車]]産業の殆どが外国企業の傘下に下ったが、外国からの投資の拡大を、しだいに自国の産業の活性化や雇用の増大に繋げて行き、その後の経済復調のきっかけにして行った([[ウィンブルドン現象]])。

その後、1997年に登場したブレア政権における経済政策の成功などにより、経済は復調し、アメリカや他のヨーロッパの国に先駆けて好景気を享受するようになったが、その反面でロンドンを除く地方は経済発展から取り残され、[[貧富の差]]の拡大や不動産価格の上昇などの問題が噴出してきている。

さらに、2008年にはアメリカ合衆国の[[サブプライムローン]]問題の影響をまともに受けて金融不安が増大した上に、資源、食料の高騰の直撃を受け、[[アリスター・ダーリング]][[財務大臣 (イギリス)|財務大臣]]が「過去60年間で恐らく最悪の下降局面に直面している」と非常に悲観的な見通しを明らかにしている<ref>{{Cite web|date=2008-08-30|url=http://sankei.jp.msn.com/economy/business/080830/biz0808301850007-n1.htm|work=産経新聞|title=「英経済、過去60年間で最悪の下降局面」英財務相|accessdate=2008-08-30 |archiveurl=https://web.archive.org/web/20080902012013/http://www.sankei.jp.msn.com/economy/business/080830/biz0808301850007-n1.htm |archivedate=2008-09-02}}</ref>。2012年{{0}}2月時点で失業率は8%を超えるまでに悪化した状態にあったが、その後は回復の兆しを見せている。

===鉱業===
[[ファイル:Oil platform in the North SeaPros.jpg|thumb|[[北海油田]]]]
イギリスの鉱業は産業革命を支えた[[石炭]]が著名である。300年以上にわたる採炭の歴史があり、石炭産業の歴史がどの国よりも長い。2002年時点においても3193万トンを採掘しているものの、ほぼ同量の石炭を輸入している。[[北海油田]]からの[[原油]]採掘量は1億1000万トンに及び、これは世界シェアの3.2%に達する。最も重要なエネルギー資源は[[天然ガス]]であり、世界シェアの4.3%(第4位)を占める。有機鉱物以外では、世界第8位となる[[塩化カリウム|カリ塩]] (KCl) 、同10位となる[[塩]] (NaCl) がある。金属鉱物には恵まれていない。最大の[[鉛]]鉱でも1000トンである。

===農業===
最も早く工業化された国であり、現在でも高度に工業化されている。農業の重要性は低下し続けており、GDPに占める農業の割合は2%を下回った。しかしながら、世界シェア10位以内に位置する農産物が8品目ある。穀物では[[オオムギ]](586万トン、世界シェア10位、以下2004年時点)、工芸作物では[[亜麻]](2万6000トン、5位)、[[テンサイ]](790万トン、9位)、[[アブラナ|ナタネ]](173万トン、5位)、[[ホップ]](2600トン、6位)である。家畜、畜産品では、[[ヒツジ]](3550万頭、7位)、[[ウール|羊毛]](6万5000トン、5位)、[[牛乳]](1480万トン、9位)が主力。

===貿易===
イギリスは産業革命成立後、自由貿易によって多大な利益を享受してきた。ただし、21世紀初頭においては貿易の比重は低下している。2004年時点の貿易依存度、すなわち国内総生産に対する輸出入額の割合は、ヨーロッパ諸国内で比較すると[[イタリア]]と並んでもっとも低い。すなわち、輸出16.1%、輸入21.3%である。

[[国際連合]]のInternational Trade Statistics Yearbook 2003によると、品目別では輸出、輸入とも工業製品が8割弱を占める。輸出では電気機械(15.2%、2003年)、機械類、自動車、医薬品、原油、輸入では電気機械 (16.3%)、自動車、機械類、衣類、医薬品の順になっている。

貿易相手国の地域構成は輸出、輸入ともヨーロッパ最大の工業国ドイツと似ている。輸出入とも対EUの比率が5割強。輸出においてはEUが53.4%(2003年)、次いでアメリカ合衆国15.0%、アジア12.1%、輸入においてはEU52.3%、アジア15.1%、アメリカ合衆国9.9%である。

国別では、主な輸出相手国はアメリカ合衆国(15.0%、2003年)、ドイツ (10.4%)、フランス (9.4%)、オランダ (5.8%)、アイルランド (6.5%)。輸入相手国はドイツ (13.5%)、アメリカ合衆国 (9.9%)、フランス (8.3%)、オランダ (6.4%)、中華人民共和国 (5.1%) である。
===不動産===
イギリスの不動産は人口の約1%の約25,000人の貴族や大企業などがイングランドの土地の48%を保有しており、未申告は貴族が家族間で秘密裏に管理していた土地と考えられている。
{|
|-
|法人企業
|style="text-align:right"|18
|<!-- 最上段 --><div style="width:180px;height:16px;background:#9999ff"></div>
|-
|銀行の経営者・寡頭政治家
|style="text-align:right"|17
|<!-- 2段目 --><div style="width:170px;height:16px;background:#9999ff"></div>
|-
|公的機関
|style="text-align:right"|8.5
|<!-- 3段目 --><div style="width:85px;height:16px;background:#9999ff"></div>
|-
|住宅保有者
|style="text-align:right"|5
|<!-- 4段目 --><div style="width:50px;height:16px;background:#9999ff"></div>
|-
|慈悲団体
|style="text-align:right"|2
|<!-- 5段目 --><div style="width:20px;height:16px;background:#9999ff"></div>
|-
|王室
|style="text-align:right"|1,4
|<!-- 6段目 --><div style="width:14px;height:16px;background:#9999ff"></div>
|-
|イングランド教会
|style="text-align:right"|0.5
|<!-- 7段目 --><div style="width:5px;height:16px;background:#9999ff"></div>
|-
|未申告
|style="text-align:right"|17
|<!-- 最下段 --><div style="width:178px;height:16px;background:#9999ff"></div>
|}

===エネルギー政策===
{{main|{{仮リンク|イギリスのエネルギー|en|Energy in the United Kingdom}}}}

イギリスの原子力発電に対する中華人民共和国の投資と技術協力を積極的に推進することで、エネルギー政策と経済力の強化に取り組んでいる<ref>[http://mainichi.jp/select/news/20151022k0000m030079000c.html 習主席:英首相と7兆円商談合意…人民元建てで国債発行へ] {{webarchive|url=https://web.archive.org/web/20151023155717/http://mainichi.jp/select/news/20151022k0000m030079000c.html |date=2015年10月23日 }}毎日新聞 2015年10月21日</ref>。2016年には、中国からの投資による原子炉の建造を承認した<ref>https://www.gov.uk/government/news/multimillion-boost-to-uk-economy-as-china-and-uk-government-sign-civil-nuclear-agreement-and-sign-agreement-to-deepen-cooperation-on-climate-change</ref>。

===通貨===
スターリング・ポンド (GBP) が使用されている。補助単位は[[ペニー]]で、1971年より1ポンドは100ペンスである。かつてポンドは[[アメリカ合衆国ドル|USドル]]が世界的に決済通貨として使われるようになる以前、イギリス帝国の経済力を背景に国際的な決済通貨として使用された。イギリスの欧州連合加盟に伴い、ヨーロッパ共通通貨であるユーロにイギリスが参加するか否かが焦点となったが、イギリス国内に反対が多く、[[欧州連合の経済通貨統合|通貨統合]]は見送られた。イングランド銀行が連合王国の[[中央銀行]]であるが、スコットランドと北アイルランドでは地元の商業銀行も独自の紙幣を発行している。イングランド銀行の紙幣にはエリザベス女王が刷られており、連合王国内で共通に通用する。スコットランド紙幣、北アイルランド紙幣ともに連合王国内で通用するが、受け取りを拒否されることもある。
2016年{{0}}6月24日、1993年に加盟した欧州連合(EU)の脱退が、国民投票によって正式に決定した。

===企業===
{{main|イギリスの企業一覧}}

====通信====
{{Main|{{仮リンク|イギリスの情報通信|en|Telecommunications in the United Kingdom}}}}
イギリスでは、ヒースロー空港などにある自動販売機で[[SIMカード]]が購入できる。[[プリペイド|プリペイド式]]となっており、スーパーなどで、通話・通信料をチャージして使う。

おもな通信業者
*[[ボーダフォン]] イギリス
*[[EE (企業)|EE]] ドイツ系の[[T-Mobile]]とフランス系(元イギリス)の[[Orange_(通信会社)|Orange]]([[:en:Orange (UK)|en]])の合弁で現在は[[BTグループ]]傘下
*[[O2]] スペイン・[[テレフォニカ]]傘下
*3(Three) 香港・[[ハチソン・ワンポア]]

==交通==
{{main|{{仮リンク|イギリスの交通|en|Transport in the United Kingdom}}}}

===道路===
{{main|{{仮リンク|イギリスの道路|en|Roads in the United Kingdom}}}}

自動車は[[対面交通|左側通行]]である。また、インド・オーストラリア・[[香港]]・[[シンガポール]]など、旧イギリス植民地の多くが左側通行を採用している。

===鉄道===
{{main|イギリスの鉄道}}
[[ファイル:Eurostar at St Pancras Jan 2008.jpg|thumb|国際列車[[ユーロスター]]の発着駅である[[セント・パンクラス駅]]]]
近代鉄道の発祥の地であり国内には鉄道網が張り巡らされ、ロンドンなどの都市には14路線ある[[地下鉄]](チューブトレイン)網が整備されている。しかし1960年代以降は設備の老朽化のために事故が多発し、さらに運行の遅延が常習化するなど問題が多発している。

小規模の民間地方鉄道の運営する地方路線の集まりとして誕生したイギリスの鉄道は、19世紀から[[20世紀]]前期にかけて、競合他社の買収などを通じて比較的大規模な少数の会社が残った。1921年にはついに[[ロンドン・ミッドランド・アンド・スコティッシュ鉄道]]、[[ロンドン・アンド・ノース・イースタン鉄道]]、[[グレート・ウェスタン鉄道]]、[[サザン鉄道 (イギリス)|サザン鉄道]]の4大鉄道会社にまとまり、これらは1948年に国有化されて[[イギリス国鉄]] (BR) となった。しかし[[1994年|1994]]~[[1997年|97年]]にBRは、旅客輸送・貨物輸送と、線路や駅などの施設を一括管理する部門に分割されて民営化された。

1994年開業したイギリス、フランス両国所有の英仏海峡トンネルは、イングランドのフォークストンからフランスのカレーまで、イギリス海峡の海底130mを長さ50.5kmで走る3本の並行したトンネルからなる。1本は貨物専用で、残り2本は乗客・車・貨物の輸送に使われる。このトンネルを使ってセント・パンクラス駅からはヨーロッパ大陸との間を結ぶ[[ユーロスター]]が運行され、[[パリ]]や[[ブリュッセル]]、[[リール (フランス)|リール]]などのヨーロッパ内の主要都市との間を結んでいる。

===海運===
周囲を海に囲まれている上、世界中に植民地を持っていたことから古くからの海運立国であり、[[P&O]]や[[キュナード・ライン]]など多くの海運会社がある。また、歴史上有名な「[[タイタニック (客船)|タイタニック号]]」や「[[クイーン・エリザベス2]]」、「[[クイーン・メリー2]]」などの著名な客船を運航している。

===航空===
{{main|{{仮リンク|イギリスの航空|en|Air transport in the United Kingdom}}}}

[[ファイル:Heathrow Terminal 5C Iwelumo-1.jpg|thumb|[[:en:London Heathrow Terminal 5|London Heathrow Terminal 5]]. [[ロンドン・ヒースロー空港]]は[[:en:World's busiest airports by international passenger traffic|国際線利用客数]]では世界随一である。]][[ファイル:Airbus A380-841 G-XLEB British Airways (10424102995).jpg|thumb|ブリティッシュ・エアウェイズ (イギリス最大の航空会社)]]


民間航空が古くから発達し、特に国際線の拡張は世界に広がる植民地間をつなぐために重要視されてきた。

現在は、[[ブリティッシュ・エアウェイズ]]や[[ヴァージン・アトランティック航空]]や[[イージージェット]]などの航空会社がある。中でもブリティッシュ・エアウェイズは、[[英国海外航空]]と[[英国欧州航空]]の2つの国営会社が合併して設立され、1987年に民営化された世界でも最大規模の航空会社で2009年にはスペインの[[イベリア航空]]と統合合意し、2011年に[[インターナショナル・エアラインズ・グループ]]を設立した。

航空機製造業も[[BAEシステムズ]]やエンジン製造の[[ロールス・ロイス・ホールディングス]]があり、1976年にはフランスとともに、[[コンコルド]]機を開発して世界初の[[超音速旅客機|超音速旅客]]輸送サービスを開始。しかし、老朽化とコスト高などにより2003年11月26日をもって運航終了となり、コンコルドは空から姿を消した。

主な空港として、ロンドンのヒースロー空港、[[ロンドン・ガトウィック空港|ガトウィック]]、[[ロンドン・スタンステッド空港|スタンステッド]]のほか、[[ロンドン・ルートン空港|ルートン]]、[[マンチェスター空港|マンチェスター]]、[[グラスゴー空港|グラスゴー]]などが挙げられる。

日本との間には2016年サマースケジュールでは、ヒースロー空港と[[成田国際空港|成田空港]]の間にブリティッシュ・エアウェイズのみ1日1便直行便を運航し、[[東京国際空港|羽田空港]]の間にも、ブリティッシュ・エアウェイズ、[[日本航空]]、[[全日本空輸]]がそれぞれ1日1便直行便を運航している。かつてはヴァージン・アトランティック航空が就航していたが2015年に撤退している。

==科学技術==
{{Main|{{仮リンク|イギリスの科学技術|en|Science and technology in the United Kingdom}}}}

17世紀の科学革命はイングランドとスコットランドが、18世紀の産業革命はイギリスが世界の中心であった。重要な発展に貢献した科学者と技術者を多数輩出している。[[アイザック・ニュートン]]、[[チャールズ・ダーウィン]]、電磁波の[[ジェームズ・クラーク・マクスウェル]]、そして最近では宇宙関係の[[スティーブン・ホーキング]]。科学上の重要な発見者には水素の[[ヘンリー・キャヴェンディッシュ]]、[[ペニシリン]]の[[アレクサンダー・フレミング]]、[[デオキシリボ核酸|DNA]]の[[フランシス・クリック]]がいる。工学面では[[グラハム・ベル]]など。科学の研究・応用は大学の重要な使命であり続け、2004年から5年間にイギリスが発表した科学論文は世界の7%を占める。学術雑誌[[ネイチャー]]や医学雑誌[[ランセット]]は世界的に著名である。

==国民==
{{main|イギリス人|{{仮リンク|イギリスの人口統計|en|Demography of the United Kingdom}}}}
{{See also|{{仮リンク|イギリスの民族|en|Ethnic groups in the United Kingdom}}}}
[[ファイル:UKpop.svg|thumb|right|イギリスの[[人口ピラミッド]]]]
イギリスの人口は2015年時点で推計6,471万人であり[[国の人口順リスト|世界第22位]]である。

「イギリス民族」という民族は存在しない。主な民族はイングランドを中心に居住する[[ゲルマン人|ゲルマン民族]]系のイングランド人([[アングロ・サクソン人]])、[[ケルト人|ケルト]]系のスコットランド人、アイルランド人、ウェールズ人だが、旧植民地出身のインド系([[印僑]])、[[アフリカ系]]、カリブ系、[[アラブ系]]や[[華僑]]なども多く住む[[多民族国家]]である。

イギリスの国籍法では、旧植民地関連の者も含め、自国民を次の六つの区分に分けている。
*GBR:British Citizen - イギリス市民
*:本国人
*BOTC:[[:en:British Overseas Territories citizen|British Overseas Territories citizen]] - [[イギリス海外領土市民]]
*:イギリスの海外領土出身者
*BOC:[[:en:British Overseas Citizen|British Overseas Citizen]] - [[イギリス海外市民]]
*:ギリシャ西岸の諸島・インド・パキスタン・マレーシアなどの旧植民地出身者のうち特殊な歴史的経緯のある者
*GBS:[[:en:British Subject|British Subject]] - [[イギリス臣民]]
*:アイルランド(北部以外)・ジブラルタルなどイギリス海外領土市民やイギリス海外市民とは別の経緯のある地域の住民で一定要件に該当する者
*BNO:[[:en:British National (Overseas)|British National (Overseas)]] - [[イギリス国民(海外)]]※「BN(O)」とも書く。
*:英国国籍で、香港の[[永住権|住民権]]も持つ人。
*BPP:[[:en:British Protected Person|British Protected Person]] - [[イギリス保護民]]

いずれの身分に属するかによって、国内での様々な取扱いで差異を生ずることがあるほか、パスポートにその区分が明示されるため、海外渡航の際も相手国により取扱いが異なることがある。例えば、日本に入国する場合、British citizen(本国人)とBritish National (Overseas)(英国籍香港人)は短期訪問目的なら[[査証]](ビザ)不要となるが、残りの四つは数日の[[観光]]訪日であってもビザが必要となる。

===言語===
{{main|{{仮リンク|イギリスの言語|en|Languages of the United Kingdom}}}}
[[ファイル:Anglospeak.svg|thumb|250px|世界の[[英語圏]]地域。濃い青色は英語が[[公用語]]または事実上の公用語になっている地域。薄い青色は英語が公用語であるが主要な言語ではない地域。]]
事実上の公用語は英語(イギリス英語)でありもっとも広く使用されているが、イングランドの主に[[コーンウォール]]でコーンウォール語、ウェールズの主に北部と中部でウェールズ語、スコットランドの主に[[ローランド地方]]でスコットランド語、ヘブリディーズ諸島の一部でスコットランド・ゲール語、北アイルランドの一部で[[:en:Ulster Scots dialects|アルスター・スコットランド語]]とアイルランド語が話されており、それぞれの構成国で公用語になっている。

特に、ウェールズでは1993年にウェールズ語が公用語になり、英語と同等の法的な地位を得た。2001年現在、ウェールズ人口の約20%がウェールズ語を使用し、その割合は僅かではあるが増加傾向にある。公文書や道路標識などはすべてウェールズ語と英語とで併記される。また、16歳までの義務教育においてウェールズ語は必修科目であり、ウェールズ語を主要な教育言語として使用し、英語は第二言語として扱う学校も多く存在する。

===宗教===
{{See also|イギリスの宗教}}
10年に一度行われるイギリス政府の国勢調査によれば、2001年、[[キリスト教徒]]が71.7%、[[イスラム教徒]]が3.0%、[[ヒンドゥー教]]徒が1.0%。
2011年、キリスト教徒59.3%、イスラム教徒4.8%、ヒンドゥー教徒が1.5%<ref>{{Cite report |publisher=Office for National Statistics |title=Religion in England and Wales 2011 |date=2012-12-11 |url=https://www.ons.gov.uk/peoplepopulationandcommunity/culturalidentity/religion/articles/religioninenglandandwales2011/2012-12-11 }}</ref>。

キリスト教の内訳は、[[英国国教会]]が62%、[[カトリック]]が13%、[[長老派]]が6%、[[メソジスト]]が3%程度と推定されている<ref>『The Changing Religious Landscape of Europe』 Hans Knippenberg</ref>。

===婚姻===
婚姻の際には、夫婦同姓・複合姓・[[夫婦別姓]]のいずれも選択可能である。また[[同性結婚]]も可能である<ref>「英国・イングランドとウェールズ、同性婚を初の合法化」朝日新聞、2014年{{0}}3月29日</ref>。また、在日英国大使館においても、同性結婚登録を行うことが可能である<ref>「在日本英国大使館・領事館で同性婚登録が可能に」 週刊金曜日 2014年{{0}}6月13日</ref><ref>https://www.gov.uk/government/news/introduction-of-same-sex-marriage-at-british-consulates-overseas.ja</ref>。

===移住===
{{main|{{仮リンク|現代イギリスにおける移民|en|Modern immigration to the United Kingdom}}|{{仮リンク|イギリスにおける外国人出生者|en|Foreign-born population of the United Kingdom}}}}
{{節スタブ}}
===教育===
{{main|イギリスの教育}}
イギリスの学校教育は地域や公立・私立の別により異なるが、5歳より小学校教育が開始される。

===医療===
{{Main|イギリスの医療}}
[[ファイル:Royal Aberdeen Children's Hospital.jpg|thumb|right|The Royal Aberdeen Children's Hospital。NHSスコットランドの小児病院]]
イギリスの医療は各地域それぞれの[[地方分権]]型であり、公的医療とプライベート診療が存在する。公的医療は[[国民保健サービス]](NHS)によりすべてのイギリス人に提供され、医学的必要性が認められる治療は大部分は自己負担なしであり、費用は一般税収を原資としている([[公費負担医療]])。NHSにはイギリス国家予算の25.2%が投じられている<ref name="ohe">{{Cite report |publisher=Office of Health Economics |title=OHE Guide to UK Health and Health Care Statistics |date=2013-08 |url=https://www.ohe.org/publications/ohe-guide-uk-health-and-health-care-statistics }}</ref>。

国全体にかかわる規制は、{{仮リンク|総合医療評議会|en|General Medical Council}}や{{仮リンク|看護助産評議会|en|Nursing and Midwifery Council}}や、また[[ロイヤル・カレッジ]]などの外部機関が行っている。しかし政策や現業の責務は、各地方行政区である4つの女王陛下の政府、北アイルランド政府、スコットランド政府、ウェールズ政府がそれぞれになっている。それぞれの運営するNHSは、各々の政策や優先度を持ち、施政に違いをもたらしている<ref>{{cite news |url=http://news.bbc.co.uk/1/hi/health/7586147.stm |title='Huge contrasts' in devolved NHS |work=BBC News |date=28 August 2008}}</ref><ref>{{cite news |url=http://news.bbc.co.uk/1/hi/health/7149423.stm |title=NHS now four different systems |work=BBC News |date=2 January 2008 |first=Nick |last=Triggle}}</ref>。

英国はGDPの8.5%を医療に支出しており、これはOECD平均と比べて-0.5%、EU平均と比べて-1%の値であった<ref>{{cite report|title=OECD Health Data 2009&nbsp;– How Does the United Kingdom Compare |publisher=OECD}}</ref>。1979年に保健支出が急増したことにより、その値はEU平均に近くなってきている<ref>{{Cite journal|url=http://www.healthp.org/node/71|title=The NHS from Thatcher to Blair |first=Peter |last=Fisher |work=NHS Consultants Association |publisher=International Association of Health Policy |quote=The Budget ... was even more generous to the NHS than had been expected amounting to an annual rise of 7.4% above the rate of inflation for the next 5 years. This would take us to 9.4% of GDP spent on health ie around EU average.}}</ref>。WHOは2000年に英国の医療制度を欧州で15位、世界で18位と評している<ref name="Who2000">{{Cite book |editor-last=Haden |editor-first=Angela |editor2-last=Campanini |editor2-first=Barbara |title=The world health report 2000&nbsp;– Health systems:improving performance |year=2000 |location=Geneva |publisher=World Health Organisation |url=http://www.who.int/whr/2000/en/whr00_en.pdf |isbn=92-4-156198-X |accessdate=5 July 2011}}</ref><ref>{{Cite journal |url=http://pages.stern.nyu.edu/~wgreene/Statistics/WHO-COMP-Study-30.pdf |title=Measuring overall health system performance for 191 countries |author=[[World Health Organization]] |publisher=New York University |accessdate=5 July 2011}}</ref>。

==文化==
{{Main|[[:en:Culture of the United Kingdom]]}}

===食文化===
{{Main|イギリス料理}}
[[フィッシュ・アンド・チップス]]や[[ローストビーフ]]、[[ウナギのゼリー寄せ]]などが有名である。{{節スタブ}}

===文学===
[[ファイル:CHANDOS3.jpg|thumb|150px|[[ウィリアム・シェイクスピア]]]]
{{Main|イギリス文学}}
多くの傑作を後世に残した[[ウィリアム・シェイクスピア]]は、[[イギリス・ルネサンス演劇]]を代表する空前絶後の詩人、および劇作家と言われる。初期のイギリス文学者としては[[ジェフリー・オブ・モンマス]]や[[ジェフリー・チョーサー]]、[[トマス・マロリー]]が著名。18世紀になると[[サミュエル・リチャードソン]]が登場する。彼の作品には3つの小説の基本条件、すなわち「フィクション性および物語性、人間同士の関係(愛情・結婚など)、個人の性格や心理」といった条件が満たされていたことから、彼は「近代小説の父」と呼ばれている。

19世紀の初めになると[[ウィリアム・ブレイク]]、[[ウィリアム・ワーズワース]]ら[[ロマン主義]]の詩人が活躍した。19世紀には小説分野において革新が見られ、[[ジェーン・オースティン]]、[[ブロンテ姉妹]]、[[チャールズ・ディケンズ]]、[[トーマス・ハーディ]]らが活躍した。19世紀末には、[[耽美主義]]の[[オスカー・ワイルド]]、現代の[[推理小説]]の生みの親[[アーサー・コナン・ドイル]]が登場。

20世紀に突入すると、「[[サイエンス・フィクション|SF]]の父」[[ハーバート・ジョージ・ウェルズ]]、[[モダニズム]]を探求した[[デーヴィッド・ハーバート・ローレンス]]、[[ヴァージニア・ウルフ]]、預言者[[ジョージ・オーウェル]]、「ミステリーの女王」[[アガサ・クリスティ]]などが出てくる。そして近年、[[ハリー・ポッターシリーズ]]の[[J・K・ローリング]]がかつての[[J・R・R・トールキン]]のような人気を世界中で湧かせている。

===哲学===
{{Main|{{仮リンク|イギリスの哲学|en|British philosophy}}}}
{{節スタブ}}
*[[イギリス経験論]]
*[[イギリス理想主義]]

===音楽===
{{Main|イギリスの音楽}}
<!-- 音楽の欄はジャンルも影響力もバラバラの人名が並んでいるため、出典に基づいた整理が必要 -->
[[クラシック音楽]]における特筆すべきイギリス人作曲家として、「ブリタニア音楽の父」[[ウィリアム・バード]]、[[ヘンリー・パーセル]]、[[エドワード・エルガー]]、[[アーサー・サリヴァン]]、[[レイフ・ヴォーン・ウィリアムズ]]、[[ベンジャミン・ブリテン]]がいる。特に欧州大陸で古典派、ロマン派が隆盛をきわめた18世紀後半から19世紀にかけて有力な作曲家が乏しかった時期もあったが、旺盛な経済力を背景に演奏市場としては隆盛を続け、ロンドンはクラシック音楽の都の一つとして現在残る。ドイツのオーケストラが地方中都市の団体でも四管フル編成を原則としているのに対し、ロンドン5大オーケストラは長年[[BBC交響楽団]]を除き(現在は[[ロンドン交響楽団]]も)総員70名台の中規模編成を貫き、大曲演奏に際してはフリー奏者を臨時補充するなどの形であったにも関わらず、それなりの世界的声価を維持してきた。一時はメンバーの共有も見られ、映画音楽の仕事が多いことが批判されることもあるものの、持ち前の合理主義によって、少なくとも英語圏では随一のクラシック演奏都市であり続けている。オペラはロンドンに[[ロイヤル・オペラ・ハウス|コヴェントガーデン王立歌劇場]]と、[[イングリッシュ・ナショナルオペラ]]を擁し、後者は世界手も珍しい英訳上演主義の団体である。

====ポピュラー音楽====
[[ファイル:The Fabs.JPG|thumb|200px|[[ビートルズ]]]]
{{Main|ロック (音楽)|{{仮リンク|ブリティッシュロック|en|British rock}}}}
[[ポピュラー音楽]](特にロックミュージック)において、イギリスは先鋭文化の発信地として世界的に有名である。1960、70年代になると[[ロック (音楽)|ロック]]が誕生し、中でも[[ビートルズ]]や[[ローリング・ストーンズ]]といった[[ロックンロール]]の影響色濃いバンドが、その表現の先駆者として活躍した。やがて[[キング・クリムゾン]]や[[ピンク・フロイド]]などの[[プログレッシブ・ロック]]や、[[クイーン (バンド)|クイーン]]、[[クリーム (バンド)|クリーム]]、[[レッド・ツェッペリン]]、[[ディープ・パープル]]、[[ブラック・サバス]]などの[[R&B]]や[[ハードロック]]がロックの更新に貢献。1970年代後半の[[パンク・ロック]]の勃興においては、アメリカ・ニューヨークからの文化を取り入れ、ロンドンを中心に[[セックス・ピストルズ]]、[[ザ・クラッシュ]]らが国民的なムーブメントを起こす。

パンク・ロック以降はインディー・ロックを中心に[[ニュー・ウェイヴ (音楽)|ニュー・ウェイヴ]]などといった新たな潮流が生まれ、[[テクノポップ]]・ドラッグミュージック文化の発達と共に[[ニュー・オーダー]]、[[ザ・ストーン・ローゼズ]]、[[グリッド]]などが、メインストリームでは[[デュラン・デュラン]]、[[デペッシュ・モード]]らの著名なバンドが生まれた。90年代は[[ブリットポップ]]や[[エレクトロニカ]]がイギリスから世界中に広まり人気を博し、[[オアシス (バンド)|オアシス]]、[[ブラー]]、[[レディオヘッド]]、[[プロディジー]]、[[マッシヴ・アタック]]などは特に目覚ましい。[[シューゲイザー]]、[[トリップホップ]]、[[ビッグビート]]などといった多くの革新的音楽ジャンルも登場した。近年では[[エイミー・ワインハウス]]、[[マクフライ]]、[[コールドプレイ]]、[[スパイス・ガールズ]]らがポップシーンに名を馳せた。

イギリスではロックやポップなどのポピュラー音楽が、国内だけでなく世界へ大きな市場を持つ主要な[[外貨]]獲得興業となっており、トニー・ブレア政権下などではクール・ブリタニアでロックミュージックに対する国策支援などが行われたりなど、その重要度は高い。アメリカ合衆国と共にカルチャーの本山として世界的な影響力を保ち続け、他国のポピュラー音楽産業の潮流への先駆性は、近年もいささかも揺るがない。

===映画===
{{Main|イギリスの映画}}
{{節スタブ}}

===コメディ===
イギリス人はユーモアのセンスが高いと言われている。また、コメディアンの多くは高学歴である。
*[[ローワン・アトキンソン]]
*[[チャールズ・チャップリン]]
*[[ピーター・セラーズ]]
*[[モンティ・パイソン]]
*[[リック・ウェイクマン]] (但し、本職は[[ミュージシャン]])

===国花===
[[国花]]はそれぞれの地域が持っている。
*イングランドは[[バラ]]
*ウェールズは[[ラッパスイセン]]([[スイセン]]の1種)。[[リーキ]]もより歴史のあるシンボルだが、リーキは花ではない。
*北アイルランドは[[シャムロック]]
*スコットランドは[[アザミ]]

===世界遺産===
イギリス国内には、[[国際連合教育科学文化機関|ユネスコ]]の[[世界遺産]]リストに登録された文化遺産が21件、自然遺産が5件ある。詳細は、[[イギリスの世界遺産]]を参照。
<gallery>
PalaceOfWestminsterAtNight.jpg|ウェストミンスター宮殿
Westminster Abbey - West Door.jpg|[[ウェストミンスター寺院]]
Edinburgh Cockburn St dsc06789.jpg|[[エディンバラ旧市街|エディンバラの旧市街]]・[[エディンバラ新市街|新市街]]
Canterbury Cathedral - Portal Nave Cross-spire.jpeg|[[カンタベリー大聖堂]]
Kew Gardens Palm House, London - July 2009.jpg|[[キューガーデン|キュー王立植物園]]
2005-06-27 - United Kingdom - England - London - Greenwich.jpg|[[グリニッジ|マリタイム・グリニッジ]]
Stonehenge2007 07 30.jpg|[[ストーンヘンジ]]
Yard2.jpg|[[ダラム城]]
Durham Kathedrale Nahaufnahme.jpg|[[ダラム大聖堂]]
Roman Baths in Bath Spa, England - July 2006.jpg|[[バース市街]]
Fountains Abbey view02 2005-08-27.jpg|[[ファウンテンズ修道院]]跡を含む[[スタッドリー王立公園]]
Blenheim Palace IMG 3673.JPG|[[ブレナム宮殿]]
Liverpool Pier Head by night.jpg|[[海商都市リヴァプール]]
Hadrian's Wall view near Greenhead.jpg|[[ローマ帝国の国境線]] ([[ハドリアヌスの長城]])
London Tower (1).JPG|[[ロンドン塔]]
</gallery>

===祝祭日===
祝祭日は、イングランド、ウェールズ、スコットランド、北アイルランドの各政府により異なる場合がある。銀行など多くの企業が休みとなることから、国民の祝祭日をバンク・ホリデー({{interlang|en|Bank holiday}})(銀行休業日)と呼ぶ。
{|class="wikitable"
!日付!!日本語表記!!現地語表記!!備考
|-
|1月{{0}}1日||[[元日]]||{{lang|en|New Year's Day}}||
|-
|1月{{0}}2日||元日翌日||-||スコットランドのみ
|-
|3月17日||[[聖パトリックの祝日|聖パトリックの日]]||{{lang|en|St. Patrick's Day}}||北アイルランドのみ
|-
|3月 - 4月||[[聖金曜日]]||{{lang|en|Good Friday}}||移動祝日
|-
|3月 - 4月||[[復活祭]]月曜日||{{lang|en|Easter Monday}}||移動祝日
|-
|5月第1月曜日||[[五月祭]]||{{lang|en|Early May Bank Holiday}}||移動祝日
|-
|5月最終月曜日||五月祭終り||{{lang|en|Spring Bank Holiday}}||移動祝日
|-
|7月12日||[[ボイン川の戦い]]記念日||{{lang|en|Battle of the Boyne (Orangemen's Day)}}||北アイルランドのみ
|-
|8月第1月曜日||夏季銀行休業日||{{lang|en|Summer Bank Holiday}}||移動祝日、スコットランドのみ
|-
|8月最終月曜日||夏季銀行休業日||{{lang|en|Summer Bank Holiday}}||移動祝日、スコットランドを除く
|-
|12月25日||[[クリスマス]]||{{lang|en|Christmas Day}}||
|-
|12月26日||[[ボクシング・デー]]||{{lang|en|Boxing Day}}||
|}
*聖金曜日を除く移動祝日は原則的に月曜日に設定されている。
*ボクシング・デー後の2日も銀行休業日であったが2005年を最後に廃止されている。

===スポーツ===
{{main|{{仮リンク|イギリスのスポーツ|en|Sport in the United Kingdom}}}}
[[ファイル:Wembley Stadium, illuminated.jpg|thumb|220px|[[ウェンブリー・スタジアム]]]]
イギリスは[[サッカー]]、[[ラグビー]]、[[クリケット]]、[[ゴルフ]]、[[ボクシング]]など多くの競技が発祥もしくは近代スポーツとして整備された地域であり、国技としても定着している。年間観客動員数は4000万人以上を集めるサッカーが他を大きく凌いでおり、[[競馬]]の600万人、ユニオンラグビーの300万、クリケット200万がそれに続く。

このうち団体球技(サッカー、ラグビー、クリケット)は発祥地域の伝統的な配慮から国際競技団体ではイギリス単体ではなく、イングランド、スコットランド、ウェールズ、北アイルランド(ラグビーに関してはアイルランドにまとめている)の4地域それぞれの加盟を認めているが、サッカーが公式なプログラムとして行われている[[近代オリンピック]]では単一国家としての出場が大原則であるため、長年出場していなかった。しかし2012年の開催が内定した[[ロンドンオリンピック (2012年)|ロンドン五輪]]では4協会が一体となった統一イギリス代表としてエントリーした。またイギリスの首都であるロンドンで[[夏季オリンピック]]を行ったのは、1948年以来64年ぶりである。ただし[[野球]]においては早くから[[野球イギリス代表|英国代表]]として、[[欧州野球選手権]]や[[ワールド・ベースボール・クラシック|WBC]]などに統一ナショナルチームを送り出している。

====サッカー====
{{main|{{仮リンク|イギリスのサッカー|en|Football in England}}}}
数多くのスポーツを誕生させたイギリスでも取り分け人気なのがサッカーである。イギリスでサッカーは「'''フットボール'''」と呼び、近代的なルールを確立したことから「'''近代サッカーの母国'''」と呼ばれ、それぞれの地域に独自のサッカー協会がある。イギリス国内でそれぞれ独立した形でサッカーリーグを展開しており、中でもイングランドの[[プレミアリーグ]]は世界的に人気である。[[フットボール・アソシエーション|イングランドサッカー協会]] (FA) などを含むイギリス国内の地域協会は全て、[[国際サッカー連盟]] (FIFA) よりも早くに発足しており、FIFA加盟国では唯一特例で国内の地域単位での加盟を認められている(以降、FIFAは海外領土など一定の自治が行われている地域協会を認可している)。その為、FIFAや[[欧州サッカー連盟]](UEFA)が主宰する各種国際大会([[FIFAワールドカップ]]・[[UEFA欧州選手権]]・[[UEFAチャンピオンズリーグ]]・[[UEFAカップ]]・[[FIFA U-20ワールドカップ]]や[[UEFA U-21欧州選手権]]などの年代別国際大会)には地域協会単位でのクラブチームやナショナルチームを参加させており、さらには7人いるFIFA副会長の一人はこの英本土4協会から選ばれる、サッカーのルールや重要事項に関しては、FIFAと英本土4協会で構成する[[国際サッカー評議会]]が決定するなど特権的な地位が与えられている。また、サッカー選手や監督がプロ競技における傑出した実績によって一代限りの騎士や勲爵士となることがある([[デビッド・ベッカム]]、[[スティーヴン・ジェラード]]や[[ボビー・ロブソン]]、[[アレックス・ファーガソン]]など)。

また、サッカーはもともとラグビーと同じく中流階級の師弟が通う[[パブリックスクール]]で近代競技として成立したが、その過程は労働者階級の娯楽として発展していった。ただ、当時のイギリスの継続的な不況からくる労働者階級の人口の割合と、それ以外の階級者も観戦していたということを注意しなければならない。労働者階級がラグビーよりもサッカーを好んでいたとされる理由として、[[フーリガン]]というあまり好ましくない暴力的なファンの存在が挙げられることもある。ただ、相次ぐフーリガン絡みの事件や事故を重く見た政府は1980年代にフーリガン規制法を制定し、スタジアムの大幅な安全基準の見直しなどを行った。各スタジアムの試合運営スタッフがスタジアムの至る所に監視カメラを設置し、特定のサポーター(フーリガン)に対する厳重な監視や入場制限を行っている。そのような取り組みの結果、スタジアムではそれまで頻発していたフーリガン絡みの事件や事故の件数が大幅に減少した。
*2007-2008シーズンにおけるイングランドサッカー入場者数<ref>2008年12月10日付けの日本経済新聞</ref>
**プレミアリーグ 1370万8875人
**[[フットボールリーグ・チャンピオンシップ|チャンピオンシップ]] 939万7036人
**[[フットボールリーグ1]] 441万2023人
**[[フットボールリーグ2]] 239万6278人
**[[FAカップ]] 201万1320人
**[[フットボールリーグカップ|リーグカップ]] 133万2841人
**[[UEFAチャンピオンズ・リーグ|CL]] 122万0127人
**UEFAカップ 46万2002人
**総動員数 3494万人

====クリケット====
クリケットは全面芝のフィールドでプレイされ、試合中には[[ティー]]タイムもある。その優雅な雰囲気から、別名「紳士のスポーツ」といわれる。イギリスでは[[上流階級]]がたしなむスポーツとされており、[[イートン]]などの名門校の体育ではクリケットは必修種目とされている。16世紀にイングランド南部で初めてプレーされた。18世紀末までには、イングランドの国民的スポーツへと発展した。大英帝国の拡大によってクリケットは海外でプレーされるようになり、19世紀中頃までには初の国際試合が開催された。イングランドは[[国際クリケット評議会]](ICC)のフルメンバーである。[[クリケット・ワールドカップ]]は[[FIFAワールドカップ]]と[[夏季オリンピック]]に次いで世界で3番目に視聴者数の多いスポーツイベントであり<ref>[https://www.theguardian.com/sport/blog/2015/feb/12/cricket-world-cup-icc-50-overs More money, more viewers and fewer runs in prospect for intriguing World Cup More money, more viewers and fewer runs in prospect for intriguing World Cup] The Guardian 2019年7月15日閲覧。</ref>、自国開催の[[2019 クリケット・ワールドカップ|2019年]]大会では[[クリケットイングランド代表|イングランド代表]]が初優勝した<ref>[https://www.theguardian.com/sport/live/2019/jul/14/new-zealand-v-england-cricket-world-cup-final-2019-live England beat New Zealand in thrilling Cricket World Cup final – as it happened!] The Guardian 2019年7月18日閲覧。</ref>。女子イングランド代表は[[女子クリケット・ワールドカップ|ワールドカップ]]で4度の優勝経験を誇る。ロンドンにある[[ローズ・クリケット・グラウンド]]はクリケットの聖地と呼ばれ、ワールドカップの決勝戦などが催された。国内リーグは[[カウンティ・チャンピオンシップ]]があり、イングランド所在の17クラブ及びウェールズ所在の1クラブ、合計18クラブにより編成される。

====競馬====
{{main|イギリスの競馬}}
近代競馬発祥の地でもある。18世紀ゴルフに次いでスポーツ組織として[[ジョッキークラブ]]が組織され、同時期に[[サラブレッド]]も成立した。どちらかと言えば[[平地競走]]よりも[[障害競走]]の方が盛んな国であり、"Favourite 100 Horses"(好きな馬100選)では[[アークル]]を初め障害馬が上位を独占した。障害の[[チェルトナムフェスティバル]]や[[グランドナショナルミーティング]]は15~25万人もの観客動員数がある。特に最大の競走であるG3[[グランドナショナル]]の売り上げは700億円近くになり、2007年現在世界で最も馬券を売り上げる競走になっている。平地競走は、[[ダービーステークス|イギリスダービー]]、[[イギリス王室|王室]]開催の[[ロイヤルアスコット開催]]が知られ、こちらも14~25万人の観客を集める。ダービーは、この競走を冠した競走が競馬を行っている国には必ずと言っていい程存在しており世界で最も知られた競走といって良いだろう。エリザベス女王も競馬ファンとして知られており、自身何頭も競走馬を所有している。

イギリスでは、日本などと違い競馬など特定の競技だけでなく全てのスポーツがギャンブルの対象となるが、売り上げはやはり競馬とサッカーが多い。競馬は1970年代を頂点に人気を失いつつあったが、後に急速に観客動員数が持ち直す傾向にある。売上高も2兆円を超え、人口当りの売り上げは香港を除けばオーストラリアに次ぐ。しかし、売り上げの多く(2003年で97.1%)が主催者側と関係のない[[ブックメーカー]]に占められるという構造的な課題がある。なお、イギリス人はどんな小さな植民地にも大抵の場合は競馬場を建設したため、独立後も旧イギリス領は競馬が盛んな国が多い。また、[[馬術]]も盛んであり、馬術のバドミントンは3日間で15万人以上の観客動員数がある。

====モータースポーツ====
イギリスは、[[モータースポーツ]]発祥の地としても知られる。[[フォーミュラ1]](F1)では多数のチャンピオンドライバーを生み出している。最近では、2009年世界チャンピオンに[[ジェンソン・バトン]]、そして2008、2014、2015、2017、2018、2019年世界チャンピオンに6度[[ルイス・ハミルトン]]が輝き、あと1回世界チャンピオンになれば、[[ミハエル・シューマッハ]]のもつ7度の記録と並ぶことになる。

過去には[[チーム・ロータス|ロータス]]や[[ティレル]]、現在も[[マクラーレン]]、[[ウィリアムズF1|ウィリアムズ]]といった数多くの名門レーシングチームが本拠を置き、車両の設計製造において常に最先端を行く。

イベントにも歴史があり、1926年に初開催された[[イギリスグランプリ]]は最も古いグランプリレースのひとつである。1950年に始まったF1グランプリはイギリスグランプリを第1戦とした。また[[世界ラリー選手権]]の一戦として組み込まれているラリー・グレート・ブリテン(1933年初開催)も同シリーズの中でもっとも古いイベントの一つである。

====野球====
{{main|ナショナルリーグ (イギリスの野球)}}
知名度は低いが、1890年に[[ブリティッシュ・ベースボール・リーグ]]という野球リーグが誕生している。[[IBAFワールドカップ]]の[[ジョン・ムーアズ・トロフィー|第1回大会]]では、アメリカ合衆国との二カ国対抗戦という形ではあったが、5回戦制のこの大会を4勝1敗で勝ち、最初の優勝国となっている。2012年{{0}}9月には、[[2013 ワールド・ベースボール・クラシック|第3回WBC]]予選に出場している。

==== カーリング ====
あまり知られてはいないが、イギリスはカーリングの強豪国でもある。<ref>「[http://www.curling.or.jp/newinfo/newrankings.html 世界ランク男女]」</ref>

==== 自転車競技 ====
国内での人気はサッカーなどには劣るが、[[ロードレース (自転車競技)|ロードレース]]や[[トラックレース]]では世界でも[[フランス]]、[[スペイン]]、[[イタリア]]と肩を並べる強豪国である。ロードレースでは2012年に[[ブラッドリー・ウィギンス]]が[[ツール・ド・フランス2012|ツール・ド・フランス]]を英国人として初めて制覇し、[[クリス・フルーム]]が2013年、2015年-2017年と同大会で総合優勝し、また2017年には[[ブエルタ・ア・エスパーニャ2017|ブエルタ・ア・エスパーニャ]]を、2018年には[[ジロ・デ・イタリア2018|ジロ・デ・イタリア]]を制覇し、[[グランツール]]と呼ばれる世界三大大会を年を跨いで連続制覇した史上3人目の選手となるなど近年目覚ましい活躍を見せている。トラックレースでもウィギンスや[[ゲラント・トーマス]]、[[エド・クランシー]]らが[[世界選手権自転車競技大会|世界選手権]]や[[オリンピック]]で数々のメダルを獲得している。

==脚注==
{{脚注ヘルプ}}
{{Reflist|2}}

==関連項目==
*[[イギリス関係記事の一覧]]

==外部リンク==
{{ウィキポータルリンク|イギリス}}
{{Sisterlinks|commons=United Kingdom|commonscat=United Kingdom|s=Category:イギリス|n=Category:イギリス|voy=United Kingdom}}
;本国政府
*[https://www.royal.uk/ 英国王室(The British Monarchy)] {{en icon}}
**{{Facebook|TheBritishMonarchy|The British Monarchy}} {{en icon}}
**{{Twitter|BritishMonarchy|BritishMonarchy}} {{en icon}}
**{{flickr|photos/britishmonarchy/|The British Monarchy}} {{en icon}}
**{{YouTube|user=TheRoyalChannel|The British Monarchy}} {{en icon}}
*[https://www.gov.uk/ 英国政府(GOV.UK)] {{en icon}}
*[https://www.gov.uk/government/organisations/prime-ministers-office-10-downing-street 英国首相府(Prime Minister's Office, 10 Downing Street)] {{en icon}}
**{{Facebook|10downingstreet|10 Downing Street}} {{en icon}}
**{{Twitter|@Number10gov|UK Prime Minister}} {{en icon}}
**{{Twitter|@Number10press|No.10 Press Office}} {{en icon}}
**{{flickr|photos/number10gov|Number 10}} {{en icon}}
**{{Pinterest|number10gov|UK Prime Minister}} {{en icon}}
**{{YouTube|user=Number10gov|Number10gov|films and features from Downing Street and the British Prime Minister}} {{en icon}}
**{{YouTube|user=DowningSt|Downing Street|archive footage from Downing Street and past British Prime Ministers}} {{en icon}}
*[https://www.gov.uk/government/world/japan.ja UK and Japan (UK and the world - GOV.UK)] {{ja icon}}{{en icon}}
**[https://www.gov.uk/government/world/organisations/british-embassy-tokyo.ja 駐日英国大使館(GOV.UK)] {{ja icon}}{{en icon}}
***{{Facebook|ukinjapan|British Embassy Tokyo}} {{ja icon}}{{en icon}}※使用言語は個々の投稿による
***{{Twitter|UKinJapan|BritishEmbassy英国大使館}} {{ja icon}}{{en icon}}※使用言語は個々の投稿による
***{{flickr|photos/uk-in-japan|UK in Japan- FCO}} {{en icon}}
***{{YouTube|user=UKinJapan|UKinJapan|British Embassy in Japan}} {{en icon}}
*[https://www.gov.uk/government/organisations/uk-visas-and-immigration UK Visas and Immigration (GOV.UK)] {{en icon}}
**[https://www.vfsglobal.co.uk/ja-jp 英国ビザ申請センター] - VFS Global Japan (上記「UK Visas and Immigration」日本地区取扱代行サイト) {{ja icon}}{{en icon}}
;日本政府内
*[https://www.mofa.go.jp/mofaj/area/uk/ 日本外務省 - 英国] {{ja icon}}
*[https://www.uk.emb-japan.go.jp/ 在英国日本国大使館] {{ja icon}}
;観光
*[https://www.visitbritain.com/jp/ja 英国政府観光庁(日本語版サイト)] {{ja icon}}
**{{Facebook|LoveGreatBritain|Love GREAT Britain}} {{en icon}}
;その他
*[https://www.jetro.go.jp/world/europe/uk/ JETRO - 英国] {{ja icon}}
*{{CIA World Factbook link|uk|United Kingdom}} {{en icon}}
*{{dmoz|Regional/Europe/United_Kingdom}} {{en icon}}
*{{wikiatlas|United Kingdom}} {{en icon}}
*{{Osmrelation|62149}}

{{Normdaten}}
{{イギリス関連の項目}}
{{ヨーロッパ}}
{{国連安全保障理事会理事国}}
{{G8}}
{{OECD}}
{{イギリス連邦}}
{{EU|1973年 - 2020年}}
{{CPLP}}
{{デフォルトソート:いきりす}}
[[Category:イギリス|*]]
[[Category:イギリス連邦加盟国]]
[[Category:英連邦王国|*]]
[[Category:G8加盟国]]
[[Category:欧州連合加盟国|元]]
[[Category:海洋国家]]
[[Category:現存する君主国]]
[[Category:島国]]
[[Category:1801年に成立した国家・領域]]

21. カテゴリ名を含む行を抽出

記事中でカテゴリ名を宣言している行を抽出せよ.

メモ

[[Category:ヘルプ|はやみひよう]]を抽出すればOK。 とりあえず、[[Category:で始まって]]で終わる行を抽出。エスケープに注意。

(参考: マークアップ早見表

re_cat = re.compile(r'\[\[Category:.+\]\]')

cats = [
    line for line in ext.split("\n")
    if re_cat.search(line)
]

for c in cats:
    print(c)
[[Category:イギリス|*]]
[[Category:イギリス連邦加盟国]]
[[Category:英連邦王国|*]]
[[Category:G8加盟国]]
[[Category:欧州連合加盟国|元]]
[[Category:海洋国家]]
[[Category:現存する君主国]]
[[Category:島国]]
[[Category:1801年に成立した国家・領域]]

22. カテゴリ名の抽出

記事のカテゴリ名を(行単位ではなく名前で)抽出せよ.

メモ

21と同様だけど、()でマッチした部分をgroupで取り出す。 [[Category:で始まって、|以外の文字を抽出して(group(1))、|で始まって|以外の文字が続くものを0個以上抽出して、]]で終わる行を抽出。

re_cat = re.compile(r'\[\[Category:([^\|]+)(\|[^\|]+)?\]\]')

for line in ext.split("\n"):
    m = re_cat.search(line)
    if m:
        print(m.group(1))
イギリス
イギリス連邦加盟国
英連邦王国
G8加盟国
欧州連合加盟国
海洋国家
現存する君主国
島国
1801年に成立した国家・領域

23. セクション構造

記事中に含まれるセクション名とそのレベル(例えば”== セクション名 ==”なら1)を表示せよ.

メモ

セクションのレベルは、最初の=の数をカウントする。 早見表的には== セクション ==はレベル2らしいけど、問題に合わせてこれをレベル1としてカウントする。

re_sec = re.compile(r'(==+)([^=]*)(==+)')

for line in ext.split("\n"):
    m = re_sec.search(line)
    if m:
        lv = len(m.group(1))-1
        hl = m.group(2)
        print(f"Lv:{lv:2}: {hl}")
Lv: 1: 国名
Lv: 1: 歴史
Lv: 1: 地理
Lv: 2: 主要都市
Lv: 2: 気候
Lv: 1: 政治
Lv: 2: 元首
Lv: 2: 法
Lv: 2: 内政
Lv: 2: 地方行政区分
Lv: 2: 外交・軍事
Lv: 1: 経済
Lv: 2: 鉱業
Lv: 2: 農業
Lv: 2: 貿易
Lv: 2: 不動産
Lv: 2: エネルギー政策
Lv: 2: 通貨
Lv: 2: 企業
Lv: 3: 通信
Lv: 1: 交通
Lv: 2: 道路
Lv: 2: 鉄道
Lv: 2: 海運
Lv: 2: 航空
Lv: 1: 科学技術
Lv: 1: 国民
Lv: 2: 言語
Lv: 2: 宗教
Lv: 2: 婚姻
Lv: 2: 移住
Lv: 2: 教育
Lv: 2: 医療
Lv: 1: 文化
Lv: 2: 食文化
Lv: 2: 文学
Lv: 2: 哲学
Lv: 2: 音楽
Lv: 3: ポピュラー音楽
Lv: 2: 映画
Lv: 2: コメディ
Lv: 2: 国花
Lv: 2: 世界遺産
Lv: 2: 祝祭日
Lv: 2: スポーツ
Lv: 3: サッカー
Lv: 3: クリケット
Lv: 3: 競馬
Lv: 3: モータースポーツ
Lv: 3: 野球
Lv: 3:  カーリング 
Lv: 3:  自転車競技 
Lv: 1: 脚注
Lv: 1: 関連項目
Lv: 1: 外部リンク

24. ファイル参照の抽出

記事から参照されているメディアファイルをすべて抜き出せ.

メモ

22と同様のやり方で、 [[ファイル:file-name.ext|thumb|説明文]]でファイル参照しているものを抽出。

re_media = re.compile(r'\[\[ファイル:([^\|]+)(\|[^\|\]]+)?\]\]')

for line in ext.split("\n"):
    m = re_media.search(line)
    if m:
        print(m.group(1))
United States Navy Band - God Save the Queen.ogg
2019 Greenwich Peninsula & Canary Wharf.jpg
Leeds CBD at night.jpg

25. テンプレートの抽出

記事中に含まれる「基礎情報」テンプレートのフィールド名と値を抽出し,辞書オブジェクトとして格納せよ.

メモ

{{基礎情報 国ではじまって}}で終わる。アイテムの区切りは|で、フィールド名=値で記載されている。 後で使うのでfields25に格納しておく。

re_begin = re.compile(r"\{\{基礎情報 国")
re_item = re.compile(r"\|([^=]+)=(.*)")
re_end = re.compile(r"\}\}")

in_template = False
fields25 = {}

for line in ext.split("\n"):

    if in_template:
        mi = re_item.match(line)
        if mi:
            k_mi = mi.group(1).strip()
            fields25[k_mi] = mi.group(2).strip() 
        elif re_end.match(line):
            in_template = False
        else:
            fields25[k_mi] += "\n" + line 

    else:
        if re_begin.match(line):
            in_template = True

print(fields25)
{'略名': 'イギリス', '日本語国名': 'グレートブリテン及び北アイルランド連合王国', '公式国名': '{{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>英語以外での正式国名:<br />\n*{{lang|gd|An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath}}([[スコットランド・ゲール語]])\n*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}([[ウェールズ語]])\n*{{lang|ga|Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann}}([[アイルランド語]])\n*{{lang|kw|An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh}}([[コーンウォール語]])\n*{{lang|sco|Unitit Kinrick o Great Breetain an Northren Ireland}}([[スコットランド語]])\n**{{lang|sco|Claught Kängrick o Docht Brätain an Norlin Airlann}}、{{lang|sco|Unitet Kängdom o Great Brittain an Norlin Airlann}}(アルスター・スコットランド語)</ref>', '国旗画像': 'Flag of the United Kingdom.svg', '国章画像': '[[ファイル:Royal Coat of Arms of the United Kingdom.svg|85px|イギリスの国章]]', '国章リンク': '([[イギリスの国章|国章]])', '標語': '{{lang|fr|[[Dieu et mon droit]]}}<br />([[フランス語]]:[[Dieu et mon droit|神と我が権利]])', '国歌': "[[女王陛下万歳|{{lang|en|God Save the Queen}}]]{{en icon}}<br />''神よ女王を護り賜え''<br />{{center|[[ファイル:United States Navy Band - God Save the Queen.ogg]]}}", '地図画像': 'Europe-UK.svg', '位置画像': 'United Kingdom (+overseas territories) in the World (+Antarctica claims).svg', '公用語': '[[英語]]', '首都': '[[ロンドン]](事実上)', '最大都市': 'ロンドン', '元首等肩書': '[[イギリスの君主|女王]]', '元首等氏名': '[[エリザベス2世]]', '首相等肩書': '[[イギリスの首相|首相]]', '首相等氏名': '[[ボリス・ジョンソン]]', '他元首等肩書1': '[[貴族院 (イギリス)|貴族院議長]]', '他元首等氏名1': '[[:en:Norman Fowler, Baron Fowler|ノーマン・ファウラー]]', '他元首等肩書2': '[[庶民院 (イギリス)|庶民院議長]]', '他元首等氏名2': '{{仮リンク|リンゼイ・ホイル|en|Lindsay Hoyle}}', '他元首等肩書3': '[[連合王国最高裁判所|最高裁判所長官]]', '他元首等氏名3': '[[:en:Brenda Hale, Baroness Hale of Richmond|ブレンダ・ヘイル]]', '面積順位': '76', '面積大きさ': '1 E11', '面積値': '244,820', '水面積率': '1.3%', '人口統計年': '2018', '人口順位': '22', '人口大きさ': '1 E7', '人口値': '6643万5600<ref>{{Cite web|url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates|title=Population estimates - Office for National Statistics|accessdate=2019-06-26|date=2019-06-26}}</ref>', '人口密度値': '271', 'GDP統計年元': '2012', 'GDP値元': '1兆5478億<ref name="imf-statistics-gdp">[http://www.imf.org/external/pubs/ft/weo/2012/02/weodata/weorept.aspx?pr.x=70&pr.y=13&sy=2010&ey=2012&scsm=1&ssd=1&sort=country&ds=.&br=1&c=112&s=NGDP%2CNGDPD%2CPPPGDP%2CPPPPC&grp=0&a=IMF>Data and Statistics>World Economic Outlook Databases>By Countrise>United Kingdom]</ref>', 'GDP統計年MER': '2012', 'GDP順位MER': '6', 'GDP値MER': '2兆4337億<ref name="imf-statistics-gdp" />', 'GDP統計年': '2012', 'GDP順位': '6', 'GDP値': '2兆3162億<ref name="imf-statistics-gdp" />', 'GDP/人': '36,727<ref name="imf-statistics-gdp" />', '建国形態': '建国', '確立形態1': '[[イングランド王国]]/[[スコットランド王国]]<br />(両国とも[[合同法 (1707年)|1707年合同法]]まで)', '確立年月日1': '927年/843年', '確立形態2': '[[グレートブリテン王国]]成立<br />(1707年合同法)', '確立年月日2': '1707年{{0}}5月{{0}}1日', '確立形態3': '[[グレートブリテン及びアイルランド連合王国]]成立<br />([[合同法 (1800年)|1800年合同法]])', '確立年月日3': '1801年{{0}}1月{{0}}1日', '確立形態4': "現在の国号「'''グレートブリテン及び北アイルランド連合王国'''」に変更", '確立年月日4': '1927年{{0}}4月12日', '通貨': '[[スターリング・ポンド|UKポンド]] (£)', '通貨コード': 'GBP', '時間帯': '±0', '夏時間': '+1', 'ISO 3166-1': 'GB / GBR', 'ccTLD': '[[.uk]] / [[.gb]]<ref>使用は.ukに比べ圧倒的少数。</ref>', '国際電話番号': '44', '注記': '<references/>'}

26. 強調マークアップの除去

25.の処理時に,テンプレートの値からMediaWikiの強調マークアップ(弱い強調,強調,強い強調のすべて)を除去してテキストに変換せよ.

メモ

早見表を参照すると、強調は下記が挙げられているので、これらを除去する。'が2個以上のものを除く。

  • 他との区別(斜体):''他との区別''
  • 強調(太字):'''強調'''
  • 斜体と強調:'''''斜体と強調'''''

後で使うのでfields26に格納しておく。

re_emph = re.compile(r"''+([^']+)''+")

fields26 = {}
for key, val in fields25.items():
    fields26[key] = re_emph.sub(r"\1",val)

print(fields26)
{'略名': 'イギリス', '日本語国名': 'グレートブリテン及び北アイルランド連合王国', '公式国名': '{{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>英語以外での正式国名:<br />\n*{{lang|gd|An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath}}([[スコットランド・ゲール語]])\n*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}([[ウェールズ語]])\n*{{lang|ga|Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann}}([[アイルランド語]])\n*{{lang|kw|An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh}}([[コーンウォール語]])\n*{{lang|sco|Unitit Kinrick o Great Breetain an Northren Ireland}}([[スコットランド語]])\n**{{lang|sco|Claught Kängrick o Docht Brätain an Norlin Airlann}}、{{lang|sco|Unitet Kängdom o Great Brittain an Norlin Airlann}}(アルスター・スコットランド語)</ref>', '国旗画像': 'Flag of the United Kingdom.svg', '国章画像': '[[ファイル:Royal Coat of Arms of the United Kingdom.svg|85px|イギリスの国章]]', '国章リンク': '([[イギリスの国章|国章]])', '標語': '{{lang|fr|[[Dieu et mon droit]]}}<br />([[フランス語]]:[[Dieu et mon droit|神と我が権利]])', '国歌': '[[女王陛下万歳|{{lang|en|God Save the Queen}}]]{{en icon}}<br />神よ女王を護り賜え<br />{{center|[[ファイル:United States Navy Band - God Save the Queen.ogg]]}}', '地図画像': 'Europe-UK.svg', '位置画像': 'United Kingdom (+overseas territories) in the World (+Antarctica claims).svg', '公用語': '[[英語]]', '首都': '[[ロンドン]](事実上)', '最大都市': 'ロンドン', '元首等肩書': '[[イギリスの君主|女王]]', '元首等氏名': '[[エリザベス2世]]', '首相等肩書': '[[イギリスの首相|首相]]', '首相等氏名': '[[ボリス・ジョンソン]]', '他元首等肩書1': '[[貴族院 (イギリス)|貴族院議長]]', '他元首等氏名1': '[[:en:Norman Fowler, Baron Fowler|ノーマン・ファウラー]]', '他元首等肩書2': '[[庶民院 (イギリス)|庶民院議長]]', '他元首等氏名2': '{{仮リンク|リンゼイ・ホイル|en|Lindsay Hoyle}}', '他元首等肩書3': '[[連合王国最高裁判所|最高裁判所長官]]', '他元首等氏名3': '[[:en:Brenda Hale, Baroness Hale of Richmond|ブレンダ・ヘイル]]', '面積順位': '76', '面積大きさ': '1 E11', '面積値': '244,820', '水面積率': '1.3%', '人口統計年': '2018', '人口順位': '22', '人口大きさ': '1 E7', '人口値': '6643万5600<ref>{{Cite web|url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates|title=Population estimates - Office for National Statistics|accessdate=2019-06-26|date=2019-06-26}}</ref>', '人口密度値': '271', 'GDP統計年元': '2012', 'GDP値元': '1兆5478億<ref name="imf-statistics-gdp">[http://www.imf.org/external/pubs/ft/weo/2012/02/weodata/weorept.aspx?pr.x=70&pr.y=13&sy=2010&ey=2012&scsm=1&ssd=1&sort=country&ds=.&br=1&c=112&s=NGDP%2CNGDPD%2CPPPGDP%2CPPPPC&grp=0&a=IMF>Data and Statistics>World Economic Outlook Databases>By Countrise>United Kingdom]</ref>', 'GDP統計年MER': '2012', 'GDP順位MER': '6', 'GDP値MER': '2兆4337億<ref name="imf-statistics-gdp" />', 'GDP統計年': '2012', 'GDP順位': '6', 'GDP値': '2兆3162億<ref name="imf-statistics-gdp" />', 'GDP/人': '36,727<ref name="imf-statistics-gdp" />', '建国形態': '建国', '確立形態1': '[[イングランド王国]]/[[スコットランド王国]]<br />(両国とも[[合同法 (1707年)|1707年合同法]]まで)', '確立年月日1': '927年/843年', '確立形態2': '[[グレートブリテン王国]]成立<br />(1707年合同法)', '確立年月日2': '1707年{{0}}5月{{0}}1日', '確立形態3': '[[グレートブリテン及びアイルランド連合王国]]成立<br />([[合同法 (1800年)|1800年合同法]])', '確立年月日3': '1801年{{0}}1月{{0}}1日', '確立形態4': '現在の国号「グレートブリテン及び北アイルランド連合王国」に変更', '確立年月日4': '1927年{{0}}4月12日', '通貨': '[[スターリング・ポンド|UKポンド]] (£)', '通貨コード': 'GBP', '時間帯': '±0', '夏時間': '+1', 'ISO 3166-1': 'GB / GBR', 'ccTLD': '[[.uk]] / [[.gb]]<ref>使用は.ukに比べ圧倒的少数。</ref>', '国際電話番号': '44', '注記': '<references/>'}

27. 内部リンクの除去

26.の処理に加えて,テンプレートの値からMediaWikiの内部リンクマークアップを除去し,テキストに変換せよ.

メモ

早見表によれば、内部リンクマークアップは下記。

  • [[記事名]]
  • [[記事名|表示文字]]
  • [[記事名#節名|表示文字]]

ファイルと被るので、?!ファイルで「ファイル」の記載のないものから、|以前の記事名を抽出、|以降は使わないので(?: )でキャプチャせずグループ化して処理する。 後で使うのでfields27に格納しておく。

re_ilink = re.compile(r"\[\[(?!ファイル)" + r"([^\]\|]+)(?:\|[^\]\|]*)*" + r"\]\]")

fields27 = {}
for key, val in fields26.items():
    fields27[key] = re_ilink.sub(r"\1", val)

print(fields27)
{'略名': 'イギリス', '日本語国名': 'グレートブリテン及び北アイルランド連合王国', '公式国名': '{{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>英語以外での正式国名:<br />\n*{{lang|gd|An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath}}(スコットランド・ゲール語)\n*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}(ウェールズ語)\n*{{lang|ga|Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann}}(アイルランド語)\n*{{lang|kw|An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh}}(コーンウォール語)\n*{{lang|sco|Unitit Kinrick o Great Breetain an Northren Ireland}}(スコットランド語)\n**{{lang|sco|Claught Kängrick o Docht Brätain an Norlin Airlann}}、{{lang|sco|Unitet Kängdom o Great Brittain an Norlin Airlann}}(アルスター・スコットランド語)</ref>', '国旗画像': 'Flag of the United Kingdom.svg', '国章画像': '[[ファイル:Royal Coat of Arms of the United Kingdom.svg|85px|イギリスの国章]]', '国章リンク': '(イギリスの国章)', '標語': '{{lang|fr|Dieu et mon droit}}<br />(フランス語:Dieu et mon droit)', '国歌': '女王陛下万歳{{en icon}}<br />神よ女王を護り賜え<br />{{center|[[ファイル:United States Navy Band - God Save the Queen.ogg]]}}', '地図画像': 'Europe-UK.svg', '位置画像': 'United Kingdom (+overseas territories) in the World (+Antarctica claims).svg', '公用語': '英語', '首都': 'ロンドン(事実上)', '最大都市': 'ロンドン', '元首等肩書': 'イギリスの君主', '元首等氏名': 'エリザベス2世', '首相等肩書': 'イギリスの首相', '首相等氏名': 'ボリス・ジョンソン', '他元首等肩書1': '貴族院 (イギリス)', '他元首等氏名1': ':en:Norman Fowler, Baron Fowler', '他元首等肩書2': '庶民院 (イギリス)', '他元首等氏名2': '{{仮リンク|リンゼイ・ホイル|en|Lindsay Hoyle}}', '他元首等肩書3': '連合王国最高裁判所', '他元首等氏名3': ':en:Brenda Hale, Baroness Hale of Richmond', '面積順位': '76', '面積大きさ': '1 E11', '面積値': '244,820', '水面積率': '1.3%', '人口統計年': '2018', '人口順位': '22', '人口大きさ': '1 E7', '人口値': '6643万5600<ref>{{Cite web|url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates|title=Population estimates - Office for National Statistics|accessdate=2019-06-26|date=2019-06-26}}</ref>', '人口密度値': '271', 'GDP統計年元': '2012', 'GDP値元': '1兆5478億<ref name="imf-statistics-gdp">[http://www.imf.org/external/pubs/ft/weo/2012/02/weodata/weorept.aspx?pr.x=70&pr.y=13&sy=2010&ey=2012&scsm=1&ssd=1&sort=country&ds=.&br=1&c=112&s=NGDP%2CNGDPD%2CPPPGDP%2CPPPPC&grp=0&a=IMF>Data and Statistics>World Economic Outlook Databases>By Countrise>United Kingdom]</ref>', 'GDP統計年MER': '2012', 'GDP順位MER': '6', 'GDP値MER': '2兆4337億<ref name="imf-statistics-gdp" />', 'GDP統計年': '2012', 'GDP順位': '6', 'GDP値': '2兆3162億<ref name="imf-statistics-gdp" />', 'GDP/人': '36,727<ref name="imf-statistics-gdp" />', '建国形態': '建国', '確立形態1': 'イングランド王国/スコットランド王国<br />(両国とも合同法 (1707年)まで)', '確立年月日1': '927年/843年', '確立形態2': 'グレートブリテン王国成立<br />(1707年合同法)', '確立年月日2': '1707年{{0}}5月{{0}}1日', '確立形態3': 'グレートブリテン及びアイルランド連合王国成立<br />(合同法 (1800年))', '確立年月日3': '1801年{{0}}1月{{0}}1日', '確立形態4': '現在の国号「グレートブリテン及び北アイルランド連合王国」に変更', '確立年月日4': '1927年{{0}}4月12日', '通貨': 'スターリング・ポンド (£)', '通貨コード': 'GBP', '時間帯': '±0', '夏時間': '+1', 'ISO 3166-1': 'GB / GBR', 'ccTLD': '.uk / .gb<ref>使用は.ukに比べ圧倒的少数。</ref>', '国際電話番号': '44', '注記': '<references/>'}

28. MediaWikiマークアップの除去

27.の処理に加えて,テンプレートの値からMediaWikiマークアップを可能な限り除去し,国の基本情報を整形せよ.

メモ

マークアップらしきものがなくなるまで、モグラたたき的に処理を追加。 後で使うのでfields28に格納しておく。

re_xlink = re.compile(r"\[http[^\]]*\]")
re_br = re.compile(r"<br */*>\n*")
re_tmpl_lang = re.compile(r"\{\{lang\|([^\|\}]+)\|([^\|\}]+)\}\}")
re_tmpl_cntr = re.compile(r"\{\{center\|([^\|\}]+)\}\}")
re_tmpl_cite = re.compile(r"\{\{Cite web\|[^\}]+\}\}")
re_tmpl_prov = re.compile(r"\{\{仮リンク\|([^\|\}]+)(?:\|[^\|\}]+)*\}\}")
re_tmpl_zero = re.compile(r"\{\{0\}\}")
re_tmpl_icon = re.compile(r"\{\{en icon\}\}")
re_tag_ref1 = re.compile(r"<ref[^>]*/>") # <ref * /> and <references />
re_tag_ref2 = re.compile(r"<ref[^>]*></ref>") # <ref *></ref>
re_tag_ref3 = re.compile(r"<ref[^>]*>([^<]+)</ref>") # <ref *>...</ref>
re_list = re.compile(r"^\*+", re.M)
re_en = re.compile(r":en:")

fields28 = {}
for key, val in fields27.items():
    v = re_xlink.sub('',val)
    v = re_br.sub('\n',v)
    v = re_tmpl_lang.sub(r'\2(\1)',v)
    v = re_tmpl_cntr.sub(r'\1',v)
    v = re_tmpl_cite.sub(r'',v)
    v = re_tmpl_prov.sub(r'\1',v)
    v = re_tmpl_zero.sub('0',v)
    v = re_tmpl_icon.sub('',v)
    v = re_tag_ref1.sub('',v)
    v = re_tag_ref2.sub('',v)
    v = re_tag_ref3.sub(r'\n\1',v)
    v = re_list.sub('',v)
    v = re_en.sub('',v)
    fields28[key] = v

for key, val in fields28.items():
    print(f"---- {key} = {''.join(val)}")
---- 略名 = イギリス
---- 日本語国名 = グレートブリテン及び北アイルランド連合王国
---- 公式国名 = United Kingdom of Great Britain and Northern Ireland(en)
英語以外での正式国名:
An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath(gd)(スコットランド・ゲール語)
Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon(cy)(ウェールズ語)
Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann(ga)(アイルランド語)
An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh(kw)(コーンウォール語)
Unitit Kinrick o Great Breetain an Northren Ireland(sco)(スコットランド語)
Claught Kängrick o Docht Brätain an Norlin Airlann(sco)、Unitet Kängdom o Great Brittain an Norlin Airlann(sco)(アルスター・スコットランド語)
---- 国旗画像 = Flag of the United Kingdom.svg
---- 国章画像 = [[ファイル:Royal Coat of Arms of the United Kingdom.svg|85px|イギリスの国章]]
---- 国章リンク = (イギリスの国章)
---- 標語 = Dieu et mon droit(fr)
(フランス語:Dieu et mon droit)
---- 国歌 = 女王陛下万歳
神よ女王を護り賜え
[[ファイル:United States Navy Band - God Save the Queen.ogg]]
---- 地図画像 = Europe-UK.svg
---- 位置画像 = United Kingdom (+overseas territories) in the World (+Antarctica claims).svg
---- 公用語 = 英語
---- 首都 = ロンドン(事実上)
---- 最大都市 = ロンドン
---- 元首等肩書 = イギリスの君主
---- 元首等氏名 = エリザベス2世
---- 首相等肩書 = イギリスの首相
---- 首相等氏名 = ボリス・ジョンソン
---- 他元首等肩書1 = 貴族院 (イギリス)
---- 他元首等氏名1 = Norman Fowler, Baron Fowler
---- 他元首等肩書2 = 庶民院 (イギリス)
---- 他元首等氏名2 = リンゼイ・ホイル
---- 他元首等肩書3 = 連合王国最高裁判所
---- 他元首等氏名3 = Brenda Hale, Baroness Hale of Richmond
---- 面積順位 = 76
---- 面積大きさ = 1 E11
---- 面積値 = 244,820
---- 水面積率 = 1.3%
---- 人口統計年 = 2018
---- 人口順位 = 22
---- 人口大きさ = 1 E7
---- 人口値 = 6643万5600
---- 人口密度値 = 271
---- GDP統計年元 = 2012
---- GDP値元 = 1兆5478億
---- GDP統計年MER = 2012
---- GDP順位MER = 6
---- GDP値MER = 2兆4337億
---- GDP統計年 = 2012
---- GDP順位 = 6
---- GDP値 = 2兆3162億
---- GDP/人 = 36,727
---- 建国形態 = 建国
---- 確立形態1 = イングランド王国/スコットランド王国
(両国とも合同法 (1707年)まで)
---- 確立年月日1 = 927年/843年
---- 確立形態2 = グレートブリテン王国成立
(1707年合同法)
---- 確立年月日2 = 1707年05月01日
---- 確立形態3 = グレートブリテン及びアイルランド連合王国成立
(合同法 (1800年))
---- 確立年月日3 = 1801年01月01日
---- 確立形態4 = 現在の国号「グレートブリテン及び北アイルランド連合王国」に変更
---- 確立年月日4 = 1927年04月12日
---- 通貨 = スターリング・ポンド (£)
---- 通貨コード = GBP
---- 時間帯 = ±0
---- 夏時間 = +1
---- ISO 3166-1 = GB / GBR
---- ccTLD = .uk / .gb
使用は.ukに比べ圧倒的少数。
---- 国際電話番号 = 44
---- 注記 = 

29. 国旗画像のURLを取得する

テンプレートの内容を利用し,国旗画像のURLを取得せよ.(ヒント: MediaWiki APIのimageinfoを呼び出して,ファイル参照をURLに変換すればよい)

メモ

MediaWiki API imageinfoのGETリクエストのを参照。 iiprop=urlを指定して、画像URLを取得する。

import requests

endpoint = "https://www.mediawiki.org/w/api.php"
filename = "File:" + fields28["国旗画像"]
params = {
    "action": "query",
    "format": "json",
    "prop": "imageinfo",
    "titles": filename,
    "iiprop": "url",
}

S = requests.Session()
R = S.get(url=endpoint, params=params)
data = R.json()

img_url = data["query"]["pages"]["-1"]["imageinfo"][0]["url"]
print(img_url)
https://upload.wikimedia.org/wikipedia/commons/8/83/Flag_of_the_United_Kingdom_%283-5%29.svg

自然言語処理100本ノック2020(Rev 2)の記録 Chapter 2

自然言語処理100本ノック2020(Rev 2)の記録(Python 3.11)

Chapter 2 UNIXコマンド

popular-names.txtは,アメリカで生まれた赤ちゃんの「名前」「性別」「人数」「年」をタブ区切り形式で格納したファイルである.以下の処理を行うプログラムを作成し,popular-names.txtを入力ファイルとして実行せよ. さらに,同様の処理をUNIXコマンドでも実行し,プログラムの実行結果を確認せよ.

メモ

Jupyterの(IPythonの)シェルコマンド!を使用。Pythonの変数に結果を代入もできる。

後々のため、次の関数を作っておく

  • head_n:イテレータの先頭N個(N行)をprintする
  • tail_n:イテレータの末尾N個(N行)をprintする
  • check:2つの結果(pythonとbash)をリストに入れて、差があった行をタプルで返す
from itertools import islice

def head_n(itr, n):
  for line in islice(itr, n):
    print(line)


def tail_n(itr, n):
  for line in reversed(list(islice(reversed(list(itr)), n))):
    print(line)


def check(rst_py, rst_sh):
  d = []  
  for line, rst in enumerate(zip(rst_py, rst_sh), start=1):
    py, sh = rst
    if py != sh:
      d.append((line,py,sh))

  print(f"- Number of different lines: {len(d)}")
  if d:
    for line, py, sh in d:
      print(f"  - (line {line:03}): {py} | {sh}")

  print("- rst_py (first 5/last 5 lines):")
  head_n(rst_py, 5)
  print(" ---")
  tail_n(rst_py, 5)

10. 行数のカウント

行数をカウントせよ.確認にはwcコマンドを用いよ.

メモ

wcコマンド:ファイル内の行数、ワード数、バイト数を出力する。

print("- python:")
with open("popular-names.txt") as f:
  print(len(f.readlines()))

# shell command
!echo "- ${SHELL}:"
!wc popular-names.txt
- python:
2780
- /bin/bash:
 2780 11120 55026 popular-names.txt

11. タブをスペースに置換

タブ1文字につきスペース1文字に置換せよ.確認にはsedコマンド,trコマンド,もしくはexpandコマンドを用いよ.

メモ

sedコマンド:ストリームエディタ。スクリプトs/hoge/fuga/gは、hogeをfugaに置換、gは繰り返しマッチ。

import re

re_TAB = re.compile(r"\t")

def substitute_tab(file):
  rst = []
  with open(file) as f:
    for line in f.readlines():
      rst.append(re_TAB.sub(' ', line.rstrip()))
  return rst

# python
rst_py = substitute_tab('popular-names.txt')

# shell
rst_sh = !sed 's/\t/ /g' popular-names.txt

# check
check(rst_py, rst_sh)
- Number of different lines: 0
- rst_py (first 5/last 5 lines):
Mary F 7065 1880
Anna F 2604 1880
Emma F 2003 1880
Elizabeth F 1939 1880
Minnie F 1746 1880
 ---
Benjamin M 13381 2018
Elijah M 12886 2018
Lucas M 12585 2018
Mason M 12435 2018
Logan M 12352 2018

12. 1列目をcol1.txtに,2列目をcol2.txtに保存

各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ.

メモ

cutコマンド:ファイルの各行からバイト、文字、フィールドをカットして出力。-f nオプションで、カットする単位をn番目のフィールド(n列目)に設定。

with open("popular-names.txt") as f0, \
     open('col1.txt', mode='w') as f1, \
     open('col2.txt', mode='w') as f2 :
  for line in f0:
    c1, c2 = line.split()[:2]
    f1.write(c1 + "\n")
    f2.write(c2 + "\n")

# python
rst_py_1 = !cat col1.txt
rst_py_2 = !cat col2.txt

# shell
rst_sh_1 = !cut -f 1 popular-names.txt
rst_sh_2 = !cut -f 2 popular-names.txt

# check
print('(col1.txt)')
check(rst_py_1, rst_sh_1)

print('(col2.txt)')
check(rst_py_2, rst_sh_2)
(col1.txt)
- Number of different lines: 0
- rst_py (first 5/last 5 lines):
Mary
Anna
Emma
Elizabeth
Minnie
 ---
Benjamin
Elijah
Lucas
Mason
Logan
(col2.txt)
- Number of different lines: 0
- rst_py (first 5/last 5 lines):
F
F
F
F
F
 ---
M
M
M
M
M

13. col1.txtとcol2.txtをマージ

12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ.確認にはpasteコマンドを用いよ.

メモ

pasteコマンド:複数ファイルの各行を結合。

merged.txtに出力。

with open('col1.txt') as f1, \
     open('col2.txt') as f2, \
     open('merged.txt', mode='w') as fw :
  for l1,l2 in zip(f1, f2):
    fw.write(f"{l1.strip()}\t{l2.strip()}\n")

# python
rst_py = !cat merged.txt

# shell
rst_sh = !paste col1.txt col2.txt

# check
check(rst_py, rst_sh)
- Number of different lines: 0
- rst_py (first 5/last 5 lines):
Mary    F
Anna    F
Emma    F
Elizabeth   F
Minnie  F
 ---
Benjamin    M
Elijah  M
Lucas   M
Mason   M
Logan   M

14. 先頭からN行を出力

自然数Nをコマンドライン引数などの手段で受け取り,入力のうち先頭のN行だけを表示せよ.確認にはheadコマンドを用いよ.

メモ

headコマンド:ファイルの先頭を表示。-nオプションで行数指定。

コマンドライン引数ありの関数はJupyterでうまく動かせなかったので、実行は別のターミナルで行った。

# knock14.py
from itertools import islice

def head_n(itr, n):
  for line in islice(itr, n):
    print(line)

if __name__ == "__main__":
  import argparse

  parser = argparse.ArgumentParser()
  parser.add_argument("file")
  parser.add_argument("num", type=int)
  args = parser.parse_args()

  with open(args.file) as f:
    head_n(map(lambda l: l.rstrip(), f.readlines()), args.num)
$ python knock14.py popular-names.txt 10
Mary    F       7065    1880
Anna    F       2604    1880
Emma    F       2003    1880
Elizabeth       F       1939    1880
Minnie  F       1746    1880
Margaret        F       1578    1880
Ida     F       1472    1880
Alice   F       1414    1880
Bertha  F       1320    1880
Sarah   F       1288    1880
$ head popular-names.txt -n 10
Mary    F       7065    1880
Anna    F       2604    1880
Emma    F       2003    1880
Elizabeth       F       1939    1880
Minnie  F       1746    1880
Margaret        F       1578    1880
Ida     F       1472    1880
Alice   F       1414    1880
Bertha  F       1320    1880
Sarah   F       1288    1880

15. 末尾のN行を出力

自然数Nをコマンドライン引数などの手段で受け取り,入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ.

メモ

headコマンド:ファイルの先頭を表示。-nオプションで行数指定。

コマンドライン引数ありの関数はJupyterでうまく動かせなかったので、実行は別のターミナルで行った。 リストにして逆順にしてリストにして逆順にして、と泥臭い感じ。。

# knock15.py
from itertools import islice

def tail_n(itr, n):
  for line in reversed(list(islice(reversed(list(itr)), n))):
    print(line)

if __name__ == "__main__":
  import argparse

  parser = argparse.ArgumentParser()
  parser.add_argument("file")
  parser.add_argument("num", type=int)
  args = parser.parse_args()

  with open(args.file) as f:
    tail_n(map(lambda l: l.rstrip(), f.readlines()), args.num)
$ python knock15.py popular-names.txt 10
Liam    M       19837   2018
Noah    M       18267   2018
William M       14516   2018
James   M       13525   2018
Oliver  M       13389   2018
Benjamin        M       13381   2018
Elijah  M       12886   2018
Lucas   M       12585   2018
Mason   M       12435   2018
Logan   M       12352   2018
$ tail popular-names.txt -n 10
Liam    M       19837   2018
Noah    M       18267   2018
William M       14516   2018
James   M       13525   2018
Oliver  M       13389   2018
Benjamin        M       13381   2018
Elijah  M       12886   2018
Lucas   M       12585   2018
Mason   M       12435   2018
Logan   M       12352   2018

16. ファイルをN分割する

自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ.

メモ

splitコマンド:ファイルを複数に分割。オプションなし引数でファイル名のprefixを指定できる。-nオプションで分割数を指定。-n l/3で「行単位で3つに分割」になる。-dでファイル名のsuffix(連番)をアルファベットでなく数字にする。

splitの挙動を見ると、バイト単位(文字単位)で等分したサイズまで1つのファイルに入れて、行の切れ目で切っている様子。なので、それを再現するようなものにしてみた。

# knock16.py
def split_n(lines, n):
  chars = list(map(len, lines)) # list of character number of each lines
  limit = sum(chars)/n # limit of characters for each files

  count = 0 # file counter
  accum = 0 # accumulator of character number in each file

  chunk = 'chunk_python_{0:02}.txt' # filename template
  fw = open(chunk.format(count), mode='w')
  for line, char in zip(lines, chars):
    if accum >= limit:
      count += 1 # increment file counter
      accum = 0 # reset accumulator

      # swich chunk file
      fw.close()
      fw = open(chunk.format(count), mode='w')
    fw.write(line)
    accum += char
  fw.close()


if __name__ == "__main__":
  import argparse

  parser = argparse.ArgumentParser()
  parser.add_argument("file")
  parser.add_argument("num", type=int)
  args = parser.parse_args()

  with open(args.file) as f:
    split_n(f.readlines(), args.num)
$ python knock16.py popular-names.txt 3
$ split popular-names.txt chunk_command_ -n l/3 -d --additional-suffix=.txt
$ head -n 4 chunk*
==> chunk_command_00.txt <==
Mary    F       7065    1880
Anna    F       2604    1880
Emma    F       2003    1880
Elizabeth       F       1939    1880

==> chunk_command_01.txt <==
Donald  M       23840   1927
Joseph  M       23506   1927
Edward  M       19113   1927
Mary    F       66872   1928

==> chunk_command_02.txt <==
Jennifer        F       63114   1974
Amy     F       29565   1974
Michelle        F       25828   1974
Heather F       23181   1974

==> chunk_python_00.txt <==
Mary    F       7065    1880
Anna    F       2604    1880
Emma    F       2003    1880
Elizabeth       F       1939    1880

==> chunk_python_01.txt <==
Donald  M       23840   1927
Joseph  M       23506   1927
Edward  M       19113   1927
Mary    F       66872   1928

==> chunk_python_02.txt <==
Jennifer        F       63114   1974
Amy     F       29565   1974
Michelle        F       25828   1974
Heather F       23181   1974
$ wc chunk*
   957   3828  18343 chunk_command_00.txt
   923   3692  18351 chunk_command_01.txt
   900   3600  18332 chunk_command_02.txt
   957   3828  18343 chunk_python_00.txt
   923   3692  18351 chunk_python_01.txt
   900   3600  18332 chunk_python_02.txt
  5560  22240 110052 total

17. 1列目の文字列の異なり

1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはcut, sort, uniqコマンドを用いよ.

メモ

uniqmanには下記noteの記載あり。事前にsortなどの処理が必要。cutで1列目を切り出して、sortで並べ替えて、uniqで重複をまとめる、をパイプでつなげる。

Note: 'uniq' does not detect repeated lines unless they are adjacent. You may want to sort the input first, or use 'sort -u' without 'uniq'.
with open('popular-names.txt') as f :
  s = set()
  for line in f:
    s.add(line.split()[0])

# python
rst_py = sorted(list(s))

# shell
rst_sh = !cut -f 1 popular-names.txt | sort | uniq

# check
check(rst_py, rst_sh)
- Number of different lines: 0
- rst_py (first 5/last 5 lines):
Abigail
Aiden
Alexander
Alexis
Alice
 ---
Tracy
Tyler
Virginia
Walter
William

18. 各行を3コラム目の数値の降順にソート

各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい).

メモ

3コラム目が同じ行のうちで順番が違うものがある。 26-27行目のElizabeth, Claraなど。

# python
with open('popular-names.txt') as f:
  rst_py = sorted(
    map(lambda l:l.strip(), f.readlines()),
    key = lambda l: int(l.split()[2])
  )

# shell
rst_sh = !sort popular-names.txt -k 3 -n

# check
check(rst_py, rst_sh)
- Number of different lines: 92
  - (line 026): Elizabeth   F   1852    1881 | Clara    F   1852    1884
  - (line 027): Clara   F   1852    1884 | Elizabeth    F   1852    1881
  - (line 050): Ida F   2049    1886 | Henry    M   2049    1891
  - (line 051): Henry   M   2049    1891 | Ida  F   2049    1886
  - (line 092): Robert  M   2334    1883 | Edward   M   2334    1904
  - (line 093): Edward  M   2334    1904 | Robert   M   2334    1883
  - (line 094): Thomas  M   2337    1886 | Edward   M   2337    1898
  - (line 095): Edward  M   2337    1898 | Thomas   M   2337    1886
  - (line 102): Minnie  F   2372    1886 | Bertha   F   2372    1891
  - (line 103): Bertha  F   2372    1891 | Minnie   F   2372    1886
  - (line 116): Henry   M   2444    1880 | Florence F   2444    1888
  - (line 117): Florence    F   2444    1888 | Henry    M   2444    1880
  - (line 141): Thomas  M   2572    1884 | Joseph   M   2572    1891
  - (line 142): Joseph  M   2572    1891 | Thomas   M   2572    1884
  - (line 175): Joseph  M   2707    1884 | Edward   M   2707    1908
  - (line 176): Edward  M   2707    1908 | Joseph   M   2707    1884
  - (line 204): Margaret    F   2917    1889 | Frank    M   2917    1893
  - (line 205): Frank   M   2917    1893 | Margaret F   2917    1889
  - (line 233): Frank   M   3067    1885 | Ethel    F   3067    1901
  - (line 234): Ethel   F   3067    1901 | Frank    M   3067    1885
  - (line 270): Ethel   F   3287    1894 | Elizabeth    F   3287    1899
  - (line 271): Elizabeth   F   3287    1899 | Ethel    F   3287    1894
  - (line 300): Florence    F   3471    1895 | Elizabeth    F   3471    1896
  - (line 301): Elizabeth   F   3471    1896 | Florence F   3471    1895
  - (line 302): Frank   M   3477    1900 | Dorothy  F   3477    1904
  - (line 303): Dorothy F   3477    1904 | Frank    M   3477    1900
  - (line 381): Ruth    F   4249    1898 | Margaret F   4249    1899
  - (line 382): Margaret    F   4249    1899 | Ruth F   4249    1898
  - (line 417): George  M   4671    1886 | Alice    F   4671    1910
  - (line 418): Alice   F   4671    1910 | George   M   4671    1886
  - (line 479): James   M   5441    1881 | George   M   5441    1910
  - (line 480): George  M   5441    1910 | James    M   5441    1881
  - (line 661): Mary    F   11754   1888 | Chloe    F   11754   2010
  - (line 662): Chloe   F   11754   2010 | Mary F   11754   1888
  - (line 726): Mary    F   13446   1895 | John M   13446   1911
  - (line 727): John    M   13446   1911 | Mary F   13446   1895
  - (line 783): Mary    F   14486   1902 | Margaret F   14486   1913
  - (line 784): Margaret    F   14486   1913 | Mary F   14486   1902
  - (line 791): Nancy   F   14544   1935 | Hannah   F   14544   2006
  - (line 792): Hannah  F   14544   2006 | Nancy    F   14544   1935
  - (line 848): Margaret    F   15239   1933 | Madison  F   15239   2009
  - (line 849): Madison F   15239   2009 | Margaret F   15239   1933
  - (line 855): Frank   M   15291   1916 | Daniel   M   15291   2011
  - (line 856): Daniel  M   15291   2011 | Frank    M   15291   1916
  - (line 885): Virginia    F   15636   1919 | Alexis   F   15636   2002
  - (line 886): Alexis  F   15636   2002 | Virginia F   15636   1919
  - (line 891): Frank   M   15702   1919 | Alexander    M   15702   2011
  - (line 892): Alexander   M   15702   2011 | Frank    M   15702   1919
  - (line 948): Richard M   16376   1921 | Helen    F   16376   1932
  - (line 949): Helen   F   16376   1932 | Richard  M   16376   1921
  - (line 977): Nancy   F   16756   1936 | Alexander    M   16756   2010
  - (line 978): Alexander   M   16756   2010 | Nancy    F   16756   1936
  - (line 1071): Heather    F   17947   1981 | Christopher  M   17947   2008
  - (line 1072): Christopher    M   17947   2008 | Heather  F   17947   1981
  - (line 1091): Kelly  F   18235   1977 | Jessica  F   18235   1998
  - (line 1092): Jessica    F   18235   1998 | Kelly    F   18235   1977
  - (line 1194): Dorothy    F   19404   1935 | Anthony  M   19404   2006
  - (line 1195): Anthony    M   19404   2006 | Dorothy  F   19404   1935
  - (line 1231): Ronald M   19835   1939 | Amy  F   19835   1980
  - (line 1232): Amy    F   19835   1980 | Ronald   M   19835   1939
  - (line 1273): Margaret   F   20295   1928 | Elizabeth    F   20295   1989
  - (line 1274): Elizabeth  F   20295   1989 | Margaret F   20295   1928
  - (line 1311): Ronald M   20730   1940 | Andrew   M   20730   2005
  - (line 1312): Andrew M   20730   2005 | Ronald   M   20730   1940
  - (line 1472): Nancy  F   23212   1944 | Amy  F   23212   1978
  - (line 1473): Amy    F   23212   1978 | Nancy    F   23212   1944
  - (line 1499): Betty  F   23641   1939 | Andrew   M   23641   2000
  - (line 1500): Andrew M   23641   2000 | Betty    F   23641   1939
  - (line 1579): Melissa    F   25095   1976 | Joshua   M   25095   2003
  - (line 1580): Joshua M   25095   2003 | Melissa  F   25095   1976
  - (line 1590): Judith F   25209   1943 | Amy  F   25209   1970
  - (line 1591): Amy    F   25209   1970 | Judith   F   25209   1943
  - (line 1615): Lisa   F   25691   1959 | Emily    F   25691   2003
  - (line 1616): Emily  F   25691   2003 | Lisa F   25691   1959
  - (line 1648): Ruth   F   26102   1920 | Jessica  F   26102   1978
  - (line 1649): Jessica    F   26102   1978 | Ruth F   26102   1920
  - (line 1655): Margaret   F   26237   1919 | Amy  F   26237   1971
  - (line 1656): Amy    F   26237   1971 | Margaret F   26237   1919
  - (line 1849): Dorothy    F   30409   1930 | Donald   M   30409   1934
  - (line 1850): Donald M   30409   1934 | Dorothy  F   30409   1930
  - (line 1902): Mark   M   31492   1970 | Justin   M   31492   1987
  - (line 1903): Justin M   31492   1987 | Mark M   31492   1970
  - (line 1965): Jennifer   F   32703   1987 | James    M   32703   1989
  - (line 1966): James  M   32703   1989 | Jennifer F   32703   1987
  - (line 2000): Lisa   F   33702   1960 | Jennifer F   33702   1969
  - (line 2001): Jennifer   F   33702   1969 | Lisa F   33702   1960
  - (line 2070): Robert M   35220   1917 | Patricia F   35220   1959
  - (line 2071): Patricia   F   35220   1959 | Robert   M   35220   1917
  - (line 2244): Robert M   40620   1918 | Barbara  F   40620   1951
  - (line 2245): Barbara    F   40620   1951 | Robert   M   40620   1918
  - (line 2400): William    M   49350   1960 | Mark M   49350   1963
  - (line 2401): Mark   M   49350   1963 | William  M   49350   1960
- rst_py (first 5/last 5 lines):
Sarah   F   1288    1880
Alice   F   1308    1881
Bertha  F   1320    1880
Bertha  F   1324    1881
Annie   F   1326    1881
 ---
Robert  M   91640   1947
Michael M   92704   1957
James   M   94757   1947
Linda   F   96211   1948
Linda   F   99689   1947

19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる

各行の1列目の文字列の出現頻度を求め,その高い順に並べて表示せよ.確認にはcut, uniq, sortコマンドを用いよ.

メモ

cutで1カラム目の名前を切り出して、sortで並べて重複する名前を一か所に集めて、uniq -cで重複をカウントして各行の先頭に追加して、sortで追加したカウントを数値として比較して(-d)逆順に並べる(-r)、をパイプラインで処理。

出願頻度が同じ行同士で順番が違うものがある。 3-4行目のJohn, Robertなど。

with open('popular-names.txt') as f:
  d = dict() # empty dictionary
  for line in f:
    name = line.split()[0]
    if name in d:
      d[name] += 1
    else:
      d[name] = 1
# python
rst_py = [f"{count:7} {name}" for name, count in sorted(d.items(), key=lambda x: x[1], reverse=True)]

# shell
rst_sh = !cut -f 1 popular-names.txt | sort | uniq -c | sort -k 1 -d -r

# check
check(rst_py, rst_sh)
- Number of different lines: 86
  - (line 003):     108 John |     108 Robert
  - (line 004):     108 Robert |     108 John
  - (line 011):      58 George |      58 Thomas
  - (line 012):      58 Thomas |      58 George
  - (line 026):      31 Daniel |      31 Joshua
  - (line 027):      31 Joshua |      31 Daniel
  - (line 034):      24 Mildred |      24 Susan
  - (line 035):      24 Betty |      24 Mildred
  - (line 036):      24 Susan |      24 Betty
  - (line 041):      20 Florence |      20 Marie
  - (line 042):      20 Marie |      20 Florence
  - (line 046):      18 Karen |      18 Olivia
  - (line 047):      18 Lisa |      18 Melissa
  - (line 048):      18 Melissa |      18 Madison
  - (line 049):      18 Madison |      18 Lisa
  - (line 050):      18 Olivia |      18 Karen
  - (line 053):      16 Ethel |      16 Sandra
  - (line 054):      16 Sandra |      16 Mark
  - (line 055):      16 Mark |      16 Ethel
  - (line 056):      15 Frances |      15 Michelle
  - (line 057):      15 Carol |      15 Isabella
  - (line 058):      15 Angela |      15 Heather
  - (line 059):      15 Michelle |      15 Frances
  - (line 060):      15 Heather |      15 Ethan
  - (line 061):      15 Ethan |      15 Carol
  - (line 062):      15 Isabella |      15 Angela
  - (line 065):      14 Amy |      14 Ava
  - (line 066):      14 Ava |      14 Amy
  - (line 068):      13 Deborah |      13 Sophia
  - (line 069):      13 Brian |      13 Nicole
  - (line 071):      13 Nicole |      13 Hannah
  - (line 072):      13 Hannah |      13 Deborah
  - (line 073):      13 Sophia |      13 Brian
  - (line 075):      12 Bertha |      12 Donna
  - (line 076):      12 Donna |      12 Bertha
  - (line 078):      10 Alice |      10 Ronald
  - (line 079):      10 Doris |      10 Noah
  - (line 080):      10 Ronald |      10 Nicholas
  - (line 081):      10 Brittany |      10 Mia
  - (line 082):      10 Nicholas |      10 Doris
  - (line 083):      10 Mia |      10 Brittany
  - (line 084):      10 Noah |      10 Alice
  - (line 085):       9 Joan |       9 Tyler
  - (line 086):       9 Debra |       9 Joan
  - (line 087):       9 Tyler |       9 Debra
  - (line 088):       8 Ida |       8 Taylor
  - (line 089):       8 Clara |       8 Mason
  - (line 091):       8 Taylor |       8 Ida
  - (line 092):       8 Alexis |       8 Clara
  - (line 093):       8 Alexander |       8 Alexis
  - (line 094):       8 Mason |       8 Alexander
  - (line 095):       7 Harry |       7 Tammy
  - (line 096):       7 Sharon |       7 Steven
  - (line 097):       7 Steven |       7 Sharon
  - (line 098):       7 Tammy |       7 Liam
  - (line 099):       7 Brandon |       7 Harry
  - (line 100):       7 Liam |       7 Brandon
  - (line 102):       5 Annie |       5 Jeffrey
  - (line 103):       5 Gary |       5 Jayden
  - (line 104):       5 Jeffrey |       5 Gary
  - (line 105):       5 Jayden |       5 Charlotte
  - (line 106):       5 Charlotte |       5 Annie
  - (line 110):       4 Austin |       4 Chloe
  - (line 111):       4 Chloe |       4 Benjamin
  - (line 112):       4 Benjamin |       4 Austin
  - (line 113):       3 Evelyn |       3 Megan
  - (line 114):       3 Megan |       3 Harper
  - (line 115):       3 Aiden |       3 Evelyn
  - (line 116):       3 Harper |       3 Elijah
  - (line 117):       3 Elijah |       3 Aiden
  - (line 118):       2 Bessie |       2 Rebecca
  - (line 119):       2 Larry |       2 Oliver
  - (line 120):       2 Rebecca |       2 Logan
  - (line 122):       2 Amelia |       2 Larry
  - (line 123):       2 Logan |       2 Bessie
  - (line 124):       2 Oliver |       2 Amelia
  - (line 126):       1 Carolyn |       1 Tracy
  - (line 127):       1 Pamela |       1 Scott
  - (line 128):       1 Lori |       1 Rachel
  - (line 129):       1 Laura |       1 Pamela
  - (line 130):       1 Tracy |       1 Lucas
  - (line 131):       1 Julie |       1 Lori
  - (line 132):       1 Scott |       1 Laura
  - (line 134):       1 Crystal |       1 Julie
  - (line 135):       1 Rachel |       1 Crystal
  - (line 136):       1 Lucas |       1 Carolyn
- rst_py (first 5/last 5 lines):
    118 James
    111 William
    108 John
    108 Robert
     92 Mary
 ---
      1 Scott
      1 Kelly
      1 Crystal
      1 Rachel
      1 Lucas

自然言語処理100本ノック2020(Rev 2)の記録 Chapter 1

自然言語処理100本ノック2020(Rev 2)の記録(Python 3.11)

Chapter 1 準備運動

00. 文字列の逆順

文字列”stressed”の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ.
string = "stressed"
print(string[::-1])
desserts

01. 「パタトクカシーー」

「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して連結した文字列を得よ.
string = "パタトクカシーー"
print(string[::2])
パトカー

02. 「パトカー」+「タクシー」=「パタトクカシーー」

「パトカー」+「タクシー」の文字を先頭から交互に連結して文字列「パタトクカシーー」を得よ.
str1 = "パトカー"
str2 = "タクシー"

print(''.join(
  map(lambda x, y: x+y, str1, str2)
))
パタトクカシーー

03. 円周率

"Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."という文を単語に分解し,各単語の(アルファベットの)文字数を先頭から出現順に並べたリストを作成せよ.

メモ

当初splitで分けようとしたが、スペースの他に”,.”も区切り文字扱いにしないと円周率にならない。 末尾にも”.”があって空白文字→0がリスト末尾に入ってしまうので、単語を正規表現で検索(re.findall)して字数カウントする方式にした。

import re
string = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."

print([
  len(m)
  for m in re.findall(r'[\w]+', string)
])
[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]

04. 元素記号

"Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."という文を単語に分解し,1, 5, 6, 7, 8, 9, 15, 16, 19番目の単語は先頭の1文字,それ以外の単語は先頭の2文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.
string = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."

# decompose string into word list
words = [ m for m in re.findall(r'[\w]+', string) ]

print({
  word[:1] if Z in [1, 5, 6, 7, 8, 9, 15, 16, 19] else word[:2] : Z
  for Z, word in enumerate(words, start=1)
})
{'H': 1, 'He': 2, 'Li': 3, 'Be': 4, 'B': 5, 'C': 6, 'N': 7, 'O': 8, 'F': 9, 'Ne': 10, 'Na': 11, 'Mi': 12, 'Al': 13, 'Si': 14, 'P': 15, 'S': 16, 'Cl': 17, 'Ar': 18, 'K': 19, 'Ca': 20}

05. n-gram

与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ.この関数を用い,”I am an NLPer”という文から単語bi-gram,文字bi-gramを得よ.
def ngram(n, seq):
  for i in range(len(seq)-n+1):
    yield seq[i:i+n]


string = "I am an NLPer"
bg_word = list(ngram(2, re.findall(r'[\w]+', string)))
bg_char = list(ngram(2, string))

print(f"word bi-gram: {bg_word}")
print(f"character bi-gram: {bg_char}")
word bi-gram: [['I', 'am'], ['am', 'an'], ['an', 'NLPer']]
character bi-gram: ['I ', ' a', 'am', 'm ', ' a', 'an', 'n ', ' N', 'NL', 'LP', 'Pe', 'er']

06. 集合

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

X = set(ngram(2, str1))
Y = set(ngram(2, str2))

print(f"X : {X}")
print(f"Y : {Y}")
print(f"X|Y :{X.union(Y)}")
print(f"X&Y :{X.intersection(Y)}")
print(f"X-Y :{X.difference(Y)}")

print(f"bi-gram 'se' is in X : {'se' in X}")
print(f"bi-gram 'se' is in Y : {'se' in Y}")
X : {'ar', 'is', 'ad', 'ap', 'di', 'se', 'ra', 'pa'}
Y : {'ar', 'ap', 'ag', 'ph', 'ra', 'gr', 'pa'}
X|Y :{'ar', 'is', 'ad', 'ap', 'ag', 'di', 'ph', 'se', 'ra', 'gr', 'pa'}
X&Y :{'ap', 'ar', 'ra', 'pa'}
X-Y :{'ad', 'di', 'is', 'se'}
bi-gram 'se' is in X : True
bi-gram 'se' is in Y : False

07. テンプレートによる文生成

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


print(tempgen(12, "気温", 22.4))
12時の気温は22.4

08. 暗号文

与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.
  • 英小文字ならば(219 - 文字コード)の文字に置換
  • その他の文字はそのまま出力
この関数を用い,英語のメッセージを暗号化・復号化せよ.
def cipher(s):
  sm = re.compile('[a-z]')
  return ''.join([
    chr(219-ord(l)) if sm.match(l) else l
    for l in s
  ])


string = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
print(cipher(string))
Nld I mvvw z wirmp, zoxlslorx lu xlfihv, zugvi gsv svzeb ovxgfivh rmeloermt jfzmgfn nvxszmrxh.

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

def typoglycemia(string):
  shuffle_inner = lambda w : w[:1] + \
                             ''.join(random.sample(w[1:-1], len(w[1:-1]))) + \
                             w[-1:]

  return ' '.join([
    shuffle_inner(word) if len(word) > 4 else word
    for word in string.split()
  ])


string = "I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
print(typoglycemia(string))
I cl’odnut bliveee that I cloud atlulacy udstnneard what I was raiendg : the pehnemnoal pewor of the haumn mind .