StatcounterとGoogleが招く黄昏、あるいは受動的Web解析の終焉

Statcounterのデータをもとに、米国におけるLinuxユーザーの急増を語る言説が話題を呼んでいる。 しかし、この数値を真に受けるのは早計だ。 実際に管理下のサイトを確認しても、NetlifyのObservabilityにおいてNon-Browser(非ブラウザ通信)が62.5%に達している。 アメリカでLinuxのユーザーが18%を超える Cloudflare Radarのデータも、同様の傾向を示している。 パーソナルコンピュータ市場のハードウェア出荷動向や半導体供給網に構造的な地殻変動が生じていない平時において、デスクトップOSのシェアが数カ月で倍増し、単月で8ポイント近く急伸する現象は、OS普及の歴史において類を見ない。 この数値が公表された直後から、オペレーティングシステムの物理的な実稼働台数を反映したものではなく、Webトラフィックの自動収集スクリプトが引き起こした観測ノイズ(アーティファクト)である可能性が技術コミュニティや業界アナリストによって指摘されている。 Statcounterの集計モデルが抱える構造的脆弱性 Statcounterの統計モデルは、世界100万以上のWebサイトに配置されたJavaScriptトラッキングタグに基づき、月間数十億件に及ぶページビューを集計する手法に依拠している。 この仕組みは手軽に大規模なトラフィック傾向を把握できる反面、OS市場シェアを推計する基盤としては致命的な欠陥を抱えている。 最大の問題は、同社がハードウェアの物理的実稼働台数(Installed Base)や認証されたユニークユーザー数(Unique Visitors)ではなく、単なる タグが発火したページビューの総和 を指標としている点にある。 集計結果は構成比(100%スケール)で正規化される。 そのため、特定のプラットフォームから生成されたページビューの絶対数が急激に膨張した場合、他OSの実利用動向に変化がなくても、そのプラットフォームのシェアが見かけ上跳ね上がり、競合OSの比率が機械的に押し下げられるゼロサム構造となっている。 Statcounterはボットやクローラを除外するフィルタリング処理を講じていると説明している。 しかし、その実体は既知のボットUser-Agent文字列や静的IPリストとのマッチングに過度に依存している。 現代のヘッドレスブラウザや自律型AIエージェントは、正規のデスクトップブラウザと完全に一致するフィンガープリントを偽装して動作する。 そのため、旧来のタグ型解析ロジックでこれらを人間のセッションと見分けて破棄することは事実上不可能に近い。 ログパース処理そのものにも深刻なデータ不整合が散見される。 2026年7月の米国デスクトップデータにおいて、2016年に呼称が廃止されたはずの旧称「OS X」が21.14%から21.81%を占める一方、現行の「macOS」が8.24%から8.6%と過小評価される異常値が記録されている。 過去にもWindows 7が不自然な急増を見せたり、Google検索の市場シェア推計で大きな誤認を生じさせて後に修正したりした経緯がある。 同社の分類器がブラウザのUser-Agent文字列やテレメトリノイズに対して極めて不安定である事実は、過去の事例からも裏付けられている。 外部テレメトリとの比較検証 Statcounterが提示した「Linuxシェア18%超」の妥当性を検証するにあたり、独立した別系統のテレメトリソースとの比較は決定的な材料を提供する。 ゲーミングプラットフォームSteamの統計、米国連邦政府公式ポータルのアクセスログ、ならびにグローバルCDNの通信ログを照合すると、実環境とStatcounterの数値との間に埋めがたい断絶が存在することが明らかになる。 PCゲーミング市場を網羅するSteamハードウェア&ソフトウェア調査(Steam Hardware & Software Survey)は、クライアントソフトウェアが端末のローカル環境からOS情報を直接取得してサンプリングを行う。 そのため、Webクローラのスクリプト実行に左右されない堅牢性を保持している。 ValveによるProton互換レイヤーの成熟やSteam Deckの普及により、SteamにおけるLinuxシェアは歴史的な高水準に達している。 それでも2026年7月時点で4.01%、英語圏ユーザーを対象とした特定区分でも8.42%にとどまっており、18%という数値とは大きく乖離している。 また、米連邦政府の公式Webサイト群を統合管理する「analytics.usa.gov」のテレメトリは、全米の一般市民による公的窓口へのアクセス実態を反映した、30日間で約16億5000万セッション規模の大規模データセットである。 同統計においてLinuxが占めるシェアは、モバイルを含む全セッション換算で約6.8%である。 モバイル端末(全体の約40%)を除外してデスクトップ環境のみに補正した場合でも、実質的なシェアは約10〜11%にとどまる。 一般市民の日常的かつ実用的な利用環境において、全米のデスクトップPCの5台に1台近くがLinuxへ置き換わったとする証拠は、公的トラフィックの精査からも確認されない。 観測プラットフォーム 測定手法・データ母集団 2026年夏時点のLinuxシェア 特性およびクローラの影響 Statcounter(米国デスクトップ) 提携サイト上のJSタグ発火(ページビュー) 18.19%(前月10.65%) ヘッドレスクローラの実行による水増しリスクが極めて高い Steam Hardware Survey クライアントによる直接システム検出 4.01%(全体) ゲーム実機ベース。Webスクレイパーの影響を原理的に排除 analytics.usa.gov 連邦政府公的Webサイトの全セッション 約6.8%(デスクトップ換算約10〜11%) 一般市民の生活動線を反映。実質シェアは約1割水準 Cloudflare Radar(北米・全通信) エッジ通過の全HTTPリクエスト 平均16%(単日最大22%〜26%) 自動化通信(AIエージェント、ボット)を含む全トラフィック Cloudflare Radar(北米・人間のみ) エッジ行動分析による人間トラフィック 約4.7% 高度な振る舞い検知でボットを除外した実効シェア Cloudflare Radarが証明するボット混入の決定打 全世界のWebトラフィックの約20%を保護、中継するCloudflareのテレメトリ基盤「Cloudflare Radar」のデータは、今回の急増現象の核心を突く反証材料となっている。 ...

9月 3, 2026 · 1 分 · 133 文字 · gorn

数字は嘘をつかないが嘘つきは数字を使う

ZDNETの記事 デスクトップ向け「Linux」、市場シェアが10%を突破–1年でほぼ倍増 には大きな問題がある。この記事の根底にあるデータについては、すでに他のメディアでも疑問が呈されている。例えば、CNETの記事 Linuxのトラフィックが北米で急増、一体なぜ? は見出しを含めて秀逸だ。「Linuxのトラフィックが北米で急増」という、データ変動の本質的要因が的確に表現されているからだ。 そして、CNETの記事を読めば、このからくりはほぼ解ける。 CloudflareのシニアプロダクトマネージャーであるLai Yi Ohlsen氏は、CNETにメールで回答し、OS別のHTTPリクエストを計測した同社のデータでは、7月4日から8月1日までに北米から発生したインターネットトラフィックのうち、Linuxが9.8%を占めたと説明した。これはStatcounterの指標とほぼ一致する。 オリジナルのStatCounterのチャートを見ると、さらなる事態がよくわかる。 赤線の「Linux」を見ると、2025年7月から2026年4月頃までは1〜2%台の底辺をずっと横ばいに推移している。それが2026年5月以降、急激な角度で上昇し、7月に突然5〜6%超へ跳ね上がっている。 数ヶ月でユーザー行動が激変するなど物理的にあり得ず、誰が見ても典型的な「ノイズ(ボット等)の混入による異常値」の挙動と考えられる。 つまり、自動化されたボットトラフィックの急増こそが、Linuxの数字の跳ね上がりの原因と考えるのが妥当だろう。 ここで注意しなければならないのは、元記事の著者であるSteven J. Vaughan-Nichols(SJVN)氏だ。同氏は長年にわたるオープンソース/Linux系の名物ライター・コラムニストであり、筋金入りのデスクトップLinux推し(デスクトップLinuxの年「Year of the Desktop Linux」を毎年のように叫び続けている人物)として知られている。 同氏にとって「Windowsのシェア低下」と「Linuxのシェア躍進」は、何よりも証明したい「悲願」だ。そのため、StatCounterのデータに異常値(ノイズ)が出た際も、冷徹なデータサイエンティスト的な検証(クロスバリデーションや異常値検出)を働かせるどころか、「ついにその時が来た!」と都合の良い証拠(バイアスを裏付けるデータ)として飛びついてしまったわけだ。 同氏レベルのベテランになれば、「StatCounterのデータには偏りがある」という反論が当然来ることは百も承知だ。だからこそ、記事中に免責(StatCounterの限界)を言い訳としてあらかじめ埋め込んでおき、批判に対する「予防線」を張る。しかし、肝心の結論(「Linuxの倍増は目覚ましい!」)は一切曲げない。 日本語版(ZDNET Japan/朝日インタラクティブ)の「盲従」 米ZDNETにおいてSJVN氏は重鎮コラムニストであり、彼の記事はよく読まれる。だからこそ日本のデスクも「SJVNが書いているから」「タイトルが煽れるから」と、ファクトチェックも訳者注も入れずにそのままスルーして翻訳配信してしまったのだろう。 Figures don’t lie but liars do figure. 数字は嘘をつかないが、嘘つきは数字を使うのだ。

8月 7, 2026 · 1 分 · 33 文字 · gorn

東京都のAI分析は「自称分析」?プロンプトとコードから見えた「思考の放棄」

AIでSNS等の情報を集約すればそれが「民意」なのか? なか2656氏が"AIでSNS等の情報を集約すればそれが「民意」なのか?“で纏めているので、考えてみる。結論を先に言ってしまうと、それは民意らしき何かであっても、民意ではない。私は法的ではなく技術的な側面から見て行こう。 AIによる集約 AIによる、要約と言うのは単純なText-to-textのタスクである。つまり、SNSからExtractされたテキストの羅列からそれに続く何らかのテキストを作る行為だ。 問題は、モデルの傾向は適正なのかと、seedの影響と言う二つの側面があり、そのアウトプットは民意なるものを適正にアウトプットしたものとは到底言えないと言える。 民意とは何か そもそも、民意とは何だろうか、数だろうか密度だろうか、おそらく、何れでもない。民主主義における合意は多数決とイコールではない。民主主義における多数決とは合意できないときのフォールバックルートに過ぎない。 従って、少数の意見でも、細大漏らさず、拾い上げなくては民意たりえないのは明白である。そして、そんなことは現状のAIモデルでは不可能だ。そもそも、何が拾われて、何が拾われないかはブラックボックスであり決定すらもない。つまり、透明性が絶対的にない。 従って、少なくとも、民意なるものの抽出には適正とは言い難い。 透明性のある抽出 従って、現実問題を言えば、旧来型のテキストマイニングの方がまだ、この場合はマシである。問題はあっても、透明性がある。つまり、単純にテキストを形態素解析して単語レベルでカウントする。全部を列挙すれば失われる情報はないはずである。共起分析もいいだろう。 AIと異なり、従来型のテキストマイニングは文脈の理解ができるわけではなく、感情の理解もできないが、民意」のように、透明性と説明責任が求められる領域においては、単なる効率性だけでなく、手法の妥当性や信頼性も考慮する必要がある。つまり、なぜ、そのアウトプットが出たのか説明できないようでは有用性を有害性は上回るリスクが否定できない。 まとめ AIによるSNS情報の集約は、世の中のトレンドや大まかな意見の傾向を把握するには有用かもしれませんが、それを「民意」と呼ぶには、ご指摘の通り、技術的な側面から見て多くの課題が残る。 Appendix なか2656氏の記事が2050東京戦略(案)のブロードリスニングを参照しているので、これを解析する。なお、この解析は東京都の公開しているコードを参照してのものである。 分析の概略 この分析は図示すると以下のような流れになっている。 graph TD A[1. データ取得] --> B(2. 埋め込みベクトルへの変換) B --> C[3. 次元削減] C --> D[4. クラスタリング] データ取得で何らかの方法で、SNSからポストを取得し、それをOpenAIのGPT系の何れかの埋め込みモデルで埋め込みベクトルに変換する。これにより、例えば、 2050年代の東京では、中学生や高校生の始業時間を遅らせてほしいです。思春期の子供たちは夜型の脳になるため、朝早くからの授業では頭がついていけないそうです。 のようなコメントは、\( [1,2,3,4] \)のような多次元のベクトルに変換される。これを次元削減して、2次元のベクトルに縮約する。これは二次元の平面上に表示するためだ。この分析ではアルゴリズムとしてUMAPが使用されている。 これを、クラスタリング手法によって、幾つかのグループにまとめる。東京都のコードではスペクトラルクラスタリングとHDBSCANが併用されている。 正確には HDBSCANによって、密度の高い領域を、クラスターとして抽出して、スペクトラルクラスタリングで最終的なクラスタを作成している。そして、クラス数はコードを読む限り6とハードコードされている。 モジュール 方法 Embedding GPT系埋め込みモデル ベクトル縮約 UMAP クラスタリング HDBSCAN クラスタリング Spectral Clustering ラベリング CountVectorizer 分析の問題 あるべき分析の戦略 データ分析の代表的なフレームワークである、CRISP-DMによれば、以下のような流れで分析は進めるべきとされている。 graph TD A[1. ビジネス理解] --> B(2. データの理解) B --> C[3. データ準備] C --> D[4. モデリング] D --> E[5. 評価] E --> F[6. 実装] プロンプトはどこから来たのか この分析で作成に使ったと思われるプロンプトが開示されている。 ...

9月 5, 2025 · 1 分 · 140 文字 · gorn

Record of Signate War

“採血データを使った心不全予測"のコンペに参加したので、解法を示します。まず、基本的に、2つの分類の予測問題は元々慣れていたので基本的なフレームとしては以下の通りです。 探索的データ分析 ベースラインモデルの作成 予測モデルの作成 探索的データ分析 まず、最初にデータを一応概観してみました。 発売中の技術同人誌 “Pythonによる探索的データ分析クックブック“でも触れている、ydata-profilingを使用しています。 import os import sys import pandas as pd import polars as pl import pyarrow as pa import numpy as np import matplotlib.pyplot as plt import seaborn as sns from ydata_profiling import ProfileReport train_df = pd.read_csv("../data/train.csv") test_df = pd.read_csv("../data/test.csv") profile = ProfileReport(train_df, title="Heart Failure Report") profile.to_file("../profile/heart_failure_report.html") ベースラインモデルの作成 基本線となるベースラインモデルを作成しました。ベースラインモデルは文字通りベースラインモデルなので、複雑なものは避けるのがセオリーです。今回は二つの分類をするタイプなので、一般化線形回帰でロジスティック回帰に持ち込むのを基本としました。また、stepwiseなどの容易さから、一旦、Rでモデリングを進めました。 コードとしては以下のシンプルきわまるものです。 require(dplyr) require(readr) require(ggplot2) require(pROC) train.df <- read.csv("../data/train.csv") test.df <- read.csv("../data/test.csv") train.df <- train.df %>% mutate( anaemia = as.factor(anaemia), diabetes = as.factor(diabetes), high_blood_pressure = as.factor(high_blood_pressure), sex = as.factor(sex), smoking = as.factor(smoking), target = as.factor(target) ) require(MASS) model <- glm(formula = target ~ age + anaemia + creatinine_phosphokinase + diabetes + ejection_fraction + high_blood_pressure + platelets + serum_creatinine + serum_sodium + sex + smoking + time, data = train.df, family = binomial) model.opt <- stepAIC(model) pred.df <- predict(model.opt, train.df, type = "response") roc_curve <- roc(train.df$target, pred.df) auc_value <- auc(roc_curve) ar_value <- (auc_value - 0.5) * 2 print(paste("AR値:", ar_value)) cat("Length of Cumulative_Percentage:", length(seq(0, 1, length.out = nrow(train.df))), "\n") cat("Length of Predicted_Positive:", length(sort(pred.df, decreasing = TRUE)), "\n") cat("Length of Actual_Positive:", length(sort(as.numeric(train.df$target), decreasing = TRUE)), "\n") sorted_predictions <- sort(pred.df, decreasing = TRUE) # 予測確率を降順に sorted_targets <- sort(as.numeric(as.character(train.df$target)), decreasing = TRUE) # 実ターゲットを降順に n <- min(length(sorted_predictions), length(sorted_targets)) cumulative_data <- data.frame( Cumulative_Percentage = seq(0, 1, length.out = n), Predicted_Positive = cumsum(sorted_predictions[1:n]), Actual_Positive = cumsum(sorted_targets[1:n]) ) ggplot(cumulative_data, aes(x = Cumulative_Percentage)) + geom_line(aes(y = Predicted_Positive, color = "モデル予測")) + geom_line(aes(y = Actual_Positive, color = "実データ")) + scale_y_continuous(name = "累積正例率", limits = c(0, max(cumulative_data$Predicted_Positive, cumulative_data$Actual_Positive))) + scale_x_continuous(name = "累積パーセンテージ", limits = c(0, 1)) + labs(title = "CAP図") + theme_minimal() 最終的には以下のCAP図になりました、 ...

5月 2, 2025 · 5 分 · 1037 文字 · Me